Skip to content

Commit 3d1554b

Browse files
authored
refactor: remove LeafExecutionPath in favor of direct item passing (#170)
## Summary - Remove `LeafExecutionPath`, `ExecutionPathItem`, and dead `Index<&LeafExecutionPath>` impl — these built index-pair paths at runtime only for the reporter to re-traverse the graph to find the same `ExecutionItem` the executor already had - Pass `&ExecutionItem` and `all_ancestors_single_node: bool` directly to `new_leaf_execution`, eliminating the round-trip graph lookup - Remove `Arc<ExecutionGraph>` from `LabeledGraphReporter` and simplify `GraphExecutionReporterBuilder::build` (no longer needs the graph) - Track single-node ancestry incrementally during graph traversal instead of recomputing it from the path - Drop `smallvec` dependency from `vite_task` crate Net: -261 lines
1 parent eb0accb commit 3d1554b

File tree

5 files changed

+110
-334
lines changed

5 files changed

+110
-334
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/vite_task/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ rusqlite = { workspace = true, features = ["bundled"] }
2929
rustc-hash = { workspace = true }
3030
serde = { workspace = true, features = ["derive", "rc"] }
3131
serde_json = { workspace = true }
32-
smallvec.workspace = true
3332
thiserror = { workspace = true }
3433
tokio = { workspace = true, features = ["rt-multi-thread", "io-std", "io-util", "macros", "sync"] }
3534
tracing = { workspace = true }

crates/vite_task/src/session/execute/mod.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use futures_util::FutureExt;
77
use tokio::io::AsyncWriteExt as _;
88
use vite_path::AbsolutePath;
99
use vite_task_plan::{
10-
ExecutionGraph, ExecutionItemKind, LeafExecutionKind, SpawnCommand, SpawnExecution,
10+
ExecutionGraph, ExecutionItemDisplay, ExecutionItemKind, LeafExecutionKind, SpawnCommand,
11+
SpawnExecution,
1112
};
1213

1314
use self::{
@@ -21,8 +22,8 @@ use super::{
2122
ExecutionError,
2223
},
2324
reporter::{
24-
ExitStatus, GraphExecutionReporter, GraphExecutionReporterBuilder, LeafExecutionPath,
25-
LeafExecutionReporter, StdioSuggestion,
25+
ExitStatus, GraphExecutionReporter, GraphExecutionReporterBuilder, LeafExecutionReporter,
26+
StdioSuggestion,
2627
},
2728
};
2829
use crate::{Session, session::execute::spawn::SpawnTrackResult};
@@ -64,16 +65,18 @@ impl ExecutionContext<'_> {
6465
/// We compute a topological order and iterate in reverse to get execution order
6566
/// (dependencies before dependents).
6667
///
67-
/// The `path_prefix` tracks our position within nested execution graphs. For the
68-
/// root call this is an empty path; for nested `Expanded` items it carries the
69-
/// path so far.
68+
/// `all_ancestors_single_node` tracks whether every graph in the ancestry chain
69+
/// (from the root down to this level) contains exactly one node. The initial call
70+
/// passes `graph.node_count() == 1`; recursive calls AND with the nested graph's
71+
/// node count.
72+
///
7073
/// Leaf-level errors are reported through the reporter and do not abort the graph.
7174
/// Cycle detection is handled at plan time, so this function cannot encounter cycles.
7275
#[expect(clippy::future_not_send, reason = "uses !Send types internally")]
7376
async fn execute_expanded_graph(
7477
&mut self,
7578
graph: &ExecutionGraph,
76-
path_prefix: &LeafExecutionPath,
79+
all_ancestors_single_node: bool,
7780
) {
7881
// `compute_topological_order()` returns nodes in topological order: for every
7982
// edge A→B, A appears before B. Since our edges mean "A depends on B",
@@ -86,18 +89,24 @@ impl ExecutionContext<'_> {
8689
for &node_ix in topo_order.iter().rev() {
8790
let task_execution = &graph[node_ix];
8891

89-
for (item_idx, item) in task_execution.items.iter().enumerate() {
90-
// Build the path for this item by appending to the prefix
91-
let mut item_path = path_prefix.clone();
92-
item_path.push(node_ix, item_idx);
93-
92+
for item in &task_execution.items {
9493
match &item.kind {
9594
ExecutionItemKind::Leaf(leaf_kind) => {
96-
self.execute_leaf(&item_path, leaf_kind).boxed_local().await;
95+
self.execute_leaf(
96+
&item.execution_item_display,
97+
leaf_kind,
98+
all_ancestors_single_node,
99+
)
100+
.boxed_local()
101+
.await;
97102
}
98103
ExecutionItemKind::Expanded(nested_graph) => {
99-
// Recurse into the nested graph, carrying the path prefix forward.
100-
self.execute_expanded_graph(nested_graph, &item_path).boxed_local().await;
104+
self.execute_expanded_graph(
105+
nested_graph,
106+
all_ancestors_single_node && nested_graph.node_count() == 1,
107+
)
108+
.boxed_local()
109+
.await;
101110
}
102111
}
103112
}
@@ -111,12 +120,14 @@ impl ExecutionContext<'_> {
111120
#[expect(clippy::future_not_send, reason = "uses !Send types internally")]
112121
async fn execute_leaf(
113122
&mut self,
114-
path: &LeafExecutionPath,
115-
leaf_execution_kind: &LeafExecutionKind,
123+
display: &ExecutionItemDisplay,
124+
leaf_kind: &LeafExecutionKind,
125+
all_ancestors_single_node: bool,
116126
) {
117-
let mut leaf_reporter = self.reporter.new_leaf_execution(path);
127+
let mut leaf_reporter =
128+
self.reporter.new_leaf_execution(display, leaf_kind, all_ancestors_single_node);
118129

119-
match leaf_execution_kind {
130+
match leaf_kind {
120131
LeafExecutionKind::InProcess(in_process_execution) => {
121132
// In-process (built-in) commands: caching is disabled, execute synchronously
122133
let mut stdio_config = leaf_reporter
@@ -401,10 +412,7 @@ impl Session<'_> {
401412
}
402413
};
403414

404-
// Wrap the graph in Arc so both the reporter and execution can reference it.
405-
// The reporter clones the Arc internally for display lookups.
406-
let graph = Arc::new(execution_graph);
407-
let mut reporter = builder.build(&graph);
415+
let mut reporter = builder.build();
408416

409417
let mut execution_context = ExecutionContext {
410418
reporter: &mut *reporter,
@@ -414,7 +422,8 @@ impl Session<'_> {
414422

415423
// Execute the graph. Leaf-level errors are reported through the reporter
416424
// and do not abort the graph. Cycle detection is handled at plan time.
417-
execution_context.execute_expanded_graph(&graph, &LeafExecutionPath::default()).await;
425+
let all_single_node = execution_graph.node_count() == 1;
426+
execution_context.execute_expanded_graph(&execution_graph, all_single_node).await;
418427

419428
// Leaf-level errors and non-zero exit statuses are tracked internally
420429
// by the reporter.

0 commit comments

Comments
 (0)