Skip to content

Commit

Permalink
fix: await all asset pipeline, even if some fail
Browse files Browse the repository at this point in the history
When a pipeline step fails, the while loop will fail fast, but this
will leave all other tasks still running in the background. Which might
lead to the case where longer running tasks (like cargo build) run,
while others abort the build.

Having a case like this, might also lead to multiple cargo builds
stacking up in the background.

It also might lead to the case where a failure, due to a missing
directory, will repeated, as repeated builds are triggered by the
initial cargo build. Because only after the initial cargo build, the
target folder will be ignored. But as the build fails fast, a new build
will be triggered, as changes to the target folder are not yet ignored.

Closes: #662
  • Loading branch information
ctron committed Jan 16, 2024
1 parent fb23677 commit 44049f9
Showing 1 changed file with 48 additions and 15 deletions.
63 changes: 48 additions & 15 deletions src/pipelines/html.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
//! Source HTML pipelines.
use std::path::PathBuf;
use std::sync::Arc;

use crate::{
config::{RtcBuild, WsProtocol},
hooks::{spawn_hooks, wait_hooks},
pipelines::{
rust::RustApp, Attrs, PipelineStage, TrunkAsset, TrunkAssetPipelineOutput,
TrunkAssetReference, TRUNK_ID,
},
processing::minify::minify_html,
};
use anyhow::{ensure, Context, Result};
use futures_util::stream::{FuturesUnordered, StreamExt};
use nipper::Document;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::fs;
use tokio::runtime::Handle;
use tokio::sync::mpsc;
use tokio::task::JoinHandle;

use crate::config::{RtcBuild, WsProtocol};
use crate::hooks::{spawn_hooks, wait_hooks};
use crate::pipelines::rust::RustApp;
use crate::pipelines::{
Attrs, PipelineStage, TrunkAsset, TrunkAssetPipelineOutput, TrunkAssetReference, TRUNK_ID,
};
use crate::processing::minify::minify_html;
use tokio::task::{JoinError, JoinHandle};

const PUBLIC_URL_MARKER_ATTR: &str = "data-trunk-public-url";
const RELOAD_SCRIPT: &str = include_str!("../autoreload.js");
Expand Down Expand Up @@ -201,12 +201,45 @@ impl HtmlPipeline {
target_html: &mut Document,
mut pipelines: AssetPipelineHandles,
) -> Result<()> {
while let Some(asset_res) = pipelines.next().await {
let mut errors = Vec::new();

/// finalize an asset pipeline with a single result
async fn finalize(
asset_res: std::result::Result<Result<TrunkAssetPipelineOutput>, JoinError>,
target_html: &mut Document,
) -> Result<()> {
let asset = asset_res
.context("failed to await asset finalization")?
.context("failed to await asset pipeline")?
.context("error from asset pipeline")?;
asset.finalize(target_html).await?;

asset
.finalize(target_html)
.await
.context("failed to finalize asset pipeline")?;

Ok(())
}

// pull all results and store their errors
while let Some(asset_res) = pipelines.next().await {
if let Err(err) = finalize(asset_res, target_html).await {
// store the error, but don't return, so that we can still await all others
errors.push(err);
}
}

// now check for errors
if let Some(first) = errors.pop() {
// if we have some, fail with the first
return Err(first.context(format!(
"HTML build pipeline failed ({} errors), showing first",
errors.len() + 1
)));
}

// return only once all pipeline steps have completed, so that we don't start a new build
// while previous pipelines are still running

Ok(())
}

Expand Down

0 comments on commit 44049f9

Please sign in to comment.