Repository navigation
feat(run): keep running independent tasks after a failure with --continue - #898
Open
jasonkuhrt wants to merge 5 commits into
Open
jasonkuhrt wants to merge 5 commits into
jasonkuhrt wants to merge 5 commits into
Conversation
…inue Without the flag, a failed task cancels the run as before. With `--continue`, a failure cancels nothing: running tasks aren't killed, new tasks keep being scheduled, and tasks that succeed are cached. The scheduler now carries whether a node failed. A failed node doesn't release its dependents, so they never start and, like tasks that fast-fail never started, aren't reported. A node stops at its first failed `&&` item, and a nested graph with a failed node counts as its parent item failing. The reporter already decides the exit status: the failed task's exit code for one failure, 1 for several. Part of voidzero-dev#822. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwWB8aXGe9BR2dR8KLH9RW
|
I'm not sure why this behavior is guarded behind a If the concern is that even when a task failed, its output may be the one contributing to other failures, simply not caching the entire graph when there is a failure, while reporting accurate exit codes for individual task seems to be a sensible default that provides the maximum amount of information. |
`--continue` is now resolved for each `vp run` level, like `--concurrency-limit`. A `vp run --continue` in a task's script applies to the tasks it runs, even when the outer run has no `--continue`, and an outer `--continue` carries over to nested runs, including ones a task starts as a separate process, through `VP_RUN_INTERNAL_CONTINUE`. The task selector keeps the flag too. The fast-fail token stays global, and graphs with `--continue` obey it. Only graphs without `--continue` cancel it, from the graph loop instead of `execute_leaf`, so a nested `--continue` run that failed also stops a fast-fail parent. A nested flag can only turn continue on, so a single token gives the same result as one per level. Each spawn gets a child token, so a task that fails to forward its output only kills its own process. `--no-bail`, pnpm's name for the same behavior, is a hidden alias. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md # crates/vt_bin/src/vtt/main.rs
With `--continue`, a task's exit never cancels the run, so stopping new tasks after Ctrl-C depends only on the Ctrl-C token. The new case presses Ctrl-C while `a` runs: `a` exits 0, and `b`, which depends on it, must not start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
When a task fails,
vp runcancels the whole run. Tasks that are still running are killed with exit code 137, no new task starts, and none of them gets a cache entry. In a recursivelintortestover many packages, the first failure hides every other package's result, and the killed tasks run again from nothing next time. #822 asks for an option to keep going.This PR is the first step of #822. Tasks that depend on a failed task don't run and aren't listed, the same way fast-fail already treats the tasks it never started. Listing them as skipped, as #822 proposes, needs decisions about the reporter and the summary format, so it's left for a follow-up.
Part of #822.
flowchart TB subgraph today["Today: a failure cancels the run"] direction TB g1["db#generate<br/>failed"]:::failed --> a1["api#lint<br/>not run"]:::notrun g1 --> w1["web#lint<br/>not run"]:::notrun u1["utils#lint<br/>killed, exit 137, not cached"]:::failed end subgraph cont["With --continue"] direction TB g2["db#generate<br/>failed"]:::failed --> a2["api#lint<br/>not run"]:::notrun g2 --> w2["web#lint<br/>not run"]:::notrun u2["utils#lint<br/>passed, cached"]:::passed end classDef failed fill:#FCEBEB,stroke:#A32D2D,color:#791F1F classDef passed fill:#EAF3DE,stroke:#3B6D11,color:#27500A classDef notrun fill:#F1EFE8,stroke:#5F5E5A,color:#444441Both runs exit with a non-zero status. Today
utils#lintis reported as failed (137) and runs again next time. With--continueit is cached, andapi#lintandweb#lintaren't listed, as with fast-fail today.Change
vp rungets a--continueflag (RunFlags::continue_on_failure). Without it, nothing changes.With it, a failed task doesn't cancel
fast_fail_token. Running tasks aren't killed, new tasks keep being scheduled, and tasks that succeed are cached through the existing path. Ctrl-C still cancels everything.In the scheduler,
execute_leaf,execute_nodeandexecute_expanded_graphnow return whether they failed. A failed node doesn't release its dependents, so their dependency counts never reach zero and they never start, directly or through other tasks. A node stops at its first failed&&item. A task whose script runsvp runfails if any task in that nested graph fails, so its own dependents don't start either.The exit status needs no change: once every task that can run has finished, the reporter already exits with the failed task's exit code for one failure, and 1 for several.
New
exit_codessnapshot cases cover a task that finishes and is cached beside a failure and replays from the cache on the next run, dependents of a failure and of a failure in a nestedvp run, a&&chain that stops at its failure, and the exit code with two failures.docs/cancellation.mddescribes the flag in its Fast-fail section.