Repository navigation
fix(engine): report the same run error whatever order parallel failures finish in - #192
Conversation
…es finish in
When several parallel branches fail under `stop` in one superstep, each
handler offered its error to the run's terminal-error slot first-writer-
wins, so the reported error followed completion order: one graph and
input could report different errors under different latencies, and
disagree with the runtime, which already names a failed step by the
lowest active-set index.
The slot now keeps a TerminalError { step, branch, error } and
terminal_error::offer keeps the lowest (superstep, active-set index):
the earliest superstep wins, then the lowest index, which for a fan-out
is the edge declaration order and the order parallel updates are folded
in. A single failure is reported unchanged.
|
Warning Review limit reached
This review includes 11 billable files and costs up to $2.75. Or wait 20 minutes for your next included review. View limit details
|
Tiny Sweeper reviewReviewed head: Verdict: Ready for maintainer review · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): fix(engine): report the same run error whatever order parallel failures finish in. Tiny Sweeper completed its review; deterministic results follow. Review snapshot
Completeness: Complete Features
TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. FindingsNo active actionable findings. Before mergeNone. Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
Resolves the CHANGELOG conflict with the engine fixes that landed on main (tinyhumansai#192-tinyhumansai#195): both Unreleased entries are kept.
Summary
When several parallel branches fail with no error handler in one superstep, the reported run error no longer depends on which branch finished first.
Root cause
finish_executionstored the failing node's structuredEngineErrorinto the run's sharedterminal_errorslot, first writer wins. In a parallel superstep the first writer is whichever activation completes first, so one graph and input could report different errors under different latencies. The graph runtime already names a failed step by the lowest active-set index, so the two could also disagree.Fix
TerminalError { step, branch, error }(src/engine/terminal_error.rs).terminal_error::offer, which keeps the lowest (superstep, active-set index). The branch index comes from the existingNodeContext::fork.Rule (documented on
offerand in the README's Reliability section)The earliest superstep wins. Within one superstep the lowest active-set index wins. For a fan-out that is the edge declaration order, the same order parallel updates are folded in. Completion order never matters. A single failure is reported unchanged, and lane failures still belong to their gather.
Validation
On a Linux build host, on main f778023 (merges cleanly onto 8b22179):
cargo test --workspace --all-features --locked: 2860 passed, 0 failed, 35 ignored (main's 35; no new ignores).-D warnings: 0. fmt: clean.cargo +1.88.0 check --all-features(MSRV): passes. rustdoc-D warnings: passes.tests/parallel_failure_order_tests.rs, copied onto unmodified main, fails on the first schedule ("delays [10, 0] reported … unhandled failure at n2"). It passes with this change.Tests
src/engine/terminal_error_tests.rs:tests/parallel_failure_order_tests.rs: two fan-out branches fail under opposite yield-count latencies, and both runs report the first-declared branch's error.Found while writing the remaining fuzz targets for #46.