Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions crates/vite_task/src/session/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,47 @@ use std::{process::ExitStatus, time::Duration};

use super::cache::CacheMiss;

/// The cache operation that failed.
#[derive(Debug)]
pub enum CacheErrorKind {
/// Cache lookup (`try_hit`) failed.
Lookup,
/// Writing the cache entry failed after successful execution.
Update,
}

impl std::fmt::Display for CacheErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Lookup => f.write_str("lookup"),
Self::Update => f.write_str("update"),
}
}
}

/// Error that occurred during a leaf execution.
///
/// Reported through [`super::reporter::LeafExecutionReporter::finish()`] and
/// displayed by the reporter.
#[derive(Debug, thiserror::Error)]
pub enum ExecutionError {
/// A cache operation failed.
#[error("Cache {kind} failed")]
Cache {
kind: CacheErrorKind,
#[source]
source: anyhow::Error,
},

/// The OS failed to spawn the child process (e.g., command not found).
#[error("Failed to spawn process")]
Spawn(#[source] anyhow::Error),

/// Creating the post-run fingerprint failed after successful execution.
#[error("Failed to create post-run fingerprint")]
PostRunFingerprint(#[source] anyhow::Error),
}

#[derive(Debug)]
pub enum OutputKind {
Stdout,
Expand Down
14 changes: 9 additions & 5 deletions crates/vite_task/src/session/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use self::{
use super::{
cache::{CommandCacheValue, ExecutionCache},
event::{
CacheDisabledReason, CacheNotUpdatedReason, CacheStatus, CacheUpdateStatus, OutputKind,
CacheDisabledReason, CacheErrorKind, CacheNotUpdatedReason, CacheStatus, CacheUpdateStatus,
ExecutionError, OutputKind,
},
reporter::{
ExitStatus, GraphExecutionReporter, GraphExecutionReporterBuilder, LeafExecutionPath,
Expand Down Expand Up @@ -186,7 +187,7 @@ pub async fn execute_spawn(
leaf_reporter.finish(
None,
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled),
Some(vite_str::format!("Cache lookup failed: {err}")),
Some(ExecutionError::Cache { kind: CacheErrorKind::Lookup, source: err }),
);
return SpawnOutcome::Failed;
}
Expand Down Expand Up @@ -263,7 +264,7 @@ pub async fn execute_spawn(
leaf_reporter.finish(
None,
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled),
Some(vite_str::format!("Failed to spawn process: {err}")),
Some(ExecutionError::Spawn(err)),
);
return SpawnOutcome::Failed;
}
Expand Down Expand Up @@ -293,13 +294,16 @@ pub async fn execute_spawn(
Ok(()) => (CacheUpdateStatus::Updated, None),
Err(err) => (
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled),
Some(vite_str::format!("Failed to update cache: {err}")),
Some(ExecutionError::Cache {
kind: CacheErrorKind::Update,
source: err,
}),
),
}
}
Err(err) => (
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled),
Some(vite_str::format!("Failed to create post-run fingerprint: {err}")),
Some(ExecutionError::PostRunFingerprint(err)),
),
}
} else {
Expand Down
17 changes: 10 additions & 7 deletions crates/vite_task/src/session/reporter/labeled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use super::{
};
use crate::session::{
cache::format_cache_status_summary,
event::{CacheStatus, CacheUpdateStatus, OutputKind, exit_status_to_code},
event::{CacheStatus, CacheUpdateStatus, ExecutionError, OutputKind, exit_status_to_code},
};

/// Information tracked for each leaf execution, used in the final summary.
Expand Down Expand Up @@ -273,29 +273,32 @@ impl<W: Write> LeafExecutionReporter for LabeledLeafReporter<W> {
self: Box<Self>,
status: Option<StdExitStatus>,
_cache_update_status: CacheUpdateStatus,
error: Option<Str>,
error: Option<ExecutionError>,
) {
let mut shared = self.shared.borrow_mut();

// Handle errors
if let Some(ref message) = error {
write_error_message(&mut shared.writer, message);
// Handle errors — format the full error chain using anyhow's `{:#}` formatter
// (joins cause chain with `: ` separators).
let has_error = error.is_some();
if let Some(error) = error {
let message: Str = vite_str::format!("{:#}", anyhow::Error::from(error));
write_error_message(&mut shared.writer, &message);

// Update the execution info if start() was called (an entry was pushed).
// Without the `self.started` guard, `last_mut()` would return a
// *different* execution's entry, corrupting its error_message.
if self.started
&& let Some(exec) = shared.executions.last_mut()
{
exec.error_message = Some(message.clone());
exec.error_message = Some(message);
}

shared.stats.failed += 1;
}

// Update failure statistics for non-zero exit status (not an error, just a failed task)
// None means success (cache hit or in-process), Some checks the actual exit status
if error.is_none() && status.is_some_and(|s| !s.success()) {
if !has_error && status.is_some_and(|s| !s.success()) {
shared.stats.failed += 1;
}

Expand Down
4 changes: 2 additions & 2 deletions crates/vite_task/src/session/reporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use vite_task_plan::{ExecutionGraph, ExecutionItem, ExecutionItemDisplay, Execut

use super::{
cache::format_cache_status_inline,
event::{CacheStatus, CacheUpdateStatus, OutputKind},
event::{CacheStatus, CacheUpdateStatus, ExecutionError, OutputKind},
};

// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Expand Down Expand Up @@ -241,7 +241,7 @@ pub trait LeafExecutionReporter {
self: Box<Self>,
status: Option<StdExitStatus>,
cache_update_status: CacheUpdateStatus,
error: Option<Str>,
error: Option<ExecutionError>,
);
}

Expand Down
12 changes: 6 additions & 6 deletions crates/vite_task/src/session/reporter/plain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
use std::io::Write;

use bstr::BString;
use vite_str::Str;

use super::{LeafExecutionReporter, StdinSuggestion, write_cache_hit_message, write_error_message};
use crate::session::event::{CacheStatus, CacheUpdateStatus, OutputKind};
use crate::session::event::{CacheStatus, CacheUpdateStatus, ExecutionError, OutputKind};

/// A self-contained [`LeafExecutionReporter`] for single-leaf executions
/// (e.g., `execute_synthetic`).
Expand Down Expand Up @@ -71,11 +70,12 @@ impl<W: Write> LeafExecutionReporter for PlainReporter<W> {
mut self: Box<Self>,
_status: Option<std::process::ExitStatus>,
_cache_update_status: CacheUpdateStatus,
error: Option<Str>,
error: Option<ExecutionError>,
) {
// Handle errors — print inline error message
if let Some(ref message) = error {
write_error_message(&mut self.writer, message);
// Handle errors — format the full error chain and print inline.
if let Some(error) = error {
let message = vite_str::format!("{:#}", anyhow::Error::from(error));
write_error_message(&mut self.writer, &message);
return;
}

Expand Down