Skip to content

Commit 5d532b6

Browse files
authored
add helper for walking a tree concurrently and deterministic (vercel/turborepo#3619)
Similar to our `try_join` helper this adds a `try_flat_map_recursive_join` helper, which allows to async expand a tree structure into all nodes. It will call the async mapper function concurrently to allow parallelism. It will handle circular and duplicate references and return all nodes in a determinstic way (breath-first).
1 parent aa3422a commit 5d532b6

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

packages/next-swc/crates/next-core/src/manifest.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use anyhow::Result;
2-
use indexmap::IndexSet;
32
use mime::APPLICATION_JSON;
4-
use turbo_tasks::primitives::StringsVc;
3+
use turbo_tasks::{primitives::StringsVc, TryFlatMapRecursiveJoinIterExt, TryJoinIterExt};
54
use turbo_tasks_fs::File;
65
use turbopack_core::asset::AssetContentVc;
76
use turbopack_dev_server::source::{
@@ -24,31 +23,47 @@ impl DevManifestContentSourceVc {
2423
#[turbo_tasks::function]
2524
async fn find_routes(self) -> Result<StringsVc> {
2625
let this = &*self.await?;
27-
let mut queue = this.page_roots.clone();
28-
let mut routes = IndexSet::new();
29-
30-
while let Some(content_source) = queue.pop() {
31-
queue.extend(content_source.get_children().await?.iter());
3226

27+
async fn content_source_to_pathname(
28+
content_source: ContentSourceVc,
29+
) -> Result<Option<String>> {
3330
// TODO This shouldn't use casts but an public api instead
3431
if let Some(api_source) = NodeApiContentSourceVc::resolve_from(content_source).await? {
35-
routes.insert(format!("/{}", api_source.get_pathname().await?));
36-
37-
continue;
32+
return Ok(Some(format!("/{}", api_source.get_pathname().await?)));
3833
}
3934

4035
if let Some(page_source) =
4136
NodeRenderContentSourceVc::resolve_from(content_source).await?
4237
{
43-
routes.insert(format!("/{}", page_source.get_pathname().await?));
44-
45-
continue;
38+
return Ok(Some(format!("/{}", page_source.get_pathname().await?)));
4639
}
40+
41+
Ok(None)
4742
}
4843

44+
async fn get_content_source_children(
45+
content_source: ContentSourceVc,
46+
) -> Result<Vec<ContentSourceVc>> {
47+
Ok(content_source.get_children().await?.clone_value())
48+
}
49+
50+
let mut routes = this
51+
.page_roots
52+
.iter()
53+
.copied()
54+
.try_flat_map_recursive_join(get_content_source_children)
55+
.await?
56+
.into_iter()
57+
.map(content_source_to_pathname)
58+
.try_join()
59+
.await?
60+
.into_iter()
61+
.flatten()
62+
.collect::<Vec<_>>();
63+
4964
routes.sort();
5065

51-
Ok(StringsVc::cell(routes.into_iter().collect()))
66+
Ok(StringsVc::cell(routes))
5267
}
5368
}
5469

packages/next-swc/crates/next-core/src/next_font_google/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
168168
Ok(r) => Some(
169169
update_stylesheet(r.await?.body.to_string(), options, scoped_font_family)
170170
.await?
171-
.clone(),
171+
.clone_value(),
172172
),
173173
Err(err) => {
174174
// Inform the user of the failure to retreive the stylesheet, but don't

0 commit comments

Comments
 (0)