1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! Parallel build pipeline for static site generation (v2).
//!
//! Uses rayon to process all extension builders concurrently.
//! Each extension independently produces pages, data, and search docs.
use std::error::Error;
use crate::builder::{BuildExt, BuildOutput, ExtBuildOutput};
use sqlx::SqlitePool;
/// Run all extension builders in parallel via rayon.
///
/// Each extension produces pages, data, and search docs independently.
/// Errors are collected per-extension and reported with context.
pub fn build_site(
db: &SqlitePool,
builders: &[Box<dyn BuildExt>],
) -> Result<BuildOutput, Box<dyn Error + Send + Sync>> {
use rayon::prelude::*;
// Capture the Tokio runtime handle ONCE here, on the runtime thread (this fn is
// called from the async `build` command). Rayon worker threads have no runtime
// bound, so `Handle::current()` inside the closure would panic. Passing the
// captured handle lets each builder `block_on` its async DB work from any thread.
let rt = tokio::runtime::Handle::current();
let results: Vec<Result<ExtBuildOutput, String>> = builders
.par_iter()
.map(|ext| {
let ext_id = ext.ext_id();
let pages = ext
.build_pages(db, &rt)
.map_err(|e| format!("[{}] build_pages: {}", ext_id, e))?;
let data = ext
.build_data(db, &rt)
.map_err(|e| format!("[{}] build_data: {}", ext_id, e))?;
let search_docs = ext
.build_search_docs(db, &rt)
.map_err(|e| format!("[{}] build_search_docs: {}", ext_id, e))?;
Ok(ExtBuildOutput {
ext_id: ext_id.to_string(),
pages,
data,
search_docs,
})
})
.collect();
// Collect errors or merge outputs
let mut outputs = Vec::with_capacity(results.len());
let mut errors = Vec::new();
for result in results {
match result {
Ok(output) => outputs.push(output),
Err(e) => errors.push(e),
}
}
if !errors.is_empty() {
return Err(format!("Build errors:\n{}", errors.join("\n")).into());
}
Ok(BuildOutput::merge(outputs))
}