fix(core): settle workflow races without waiting for losers

XY
5d ago
+215-100

PR Checklist

  • The commit message follows the contribution guidelines.

Bugs / Features

  • Related issue(s) linked
  • Tests for the changes have been added
  • Docs have been added / updated
  • Changesets have been added

Problem

A workflow using andRace chooses the first settled child, then awaits every child to collect timing information. A slow or permanently pending losing operation therefore blocks workflow.run() and downstream steps, including when the first child rejects.

Change

Return or propagate the first settled result immediately. Close the winning child span using its completed/error/suspended/cancelled outcome and the other child spans as skipped, with rejection handlers attached to every branch so late losing failures are observed. Remove ended workflow step spans from the serverless active span bridge; otherwise a pending loser remains the active span after the workflow returns.

Losing operations continue running: this change does not cancel promises or change the race into first-success semantics.

Validation

Validated head: af90f4040e52f7d99a5f1a19a3ec9268a7415fd3.

  • Public createWorkflow(...andRace).run() regression tests fail on the original implementation for both success and first rejection while a loser is held pending, and pass after the fix.
  • Public suspend() and abort() winners retain suspended/cancelled child-span states; both regressions fail before the control-flow classification fix and pass after it.
  • Actual ServerlessVoltAgentObservability regression fails without the bridge cleanup and passes with it. Tests verify every race child span ends once and a late losing rejection does not mutate ended spans.
  • Core suite with type tests: 111 files passed; 1,406 passed, 2 skipped, 1 todo; no type errors.
  • Core tsc --noEmit and CJS/ESM/declaration builds passed; internal build passed.
  • Changed TypeScript files pass Biome; changeset passes Prettier; git diff --check passes.

Notes for reviewers

Prepared with AI assistance. The implementation and regression tests were validated with the commands and red/green results above. No existing issue is linked; the bug is reproduced through the documented workflow API. Existing first-completed documentation already describes the corrected behavior.

Summary by CodeRabbit

  • Bug Fixes
    • Workflow races now return a result or report an error as soon as the first step settles, rather than waiting for all steps to finish.
    • A winning error is reported immediately, and later failures from losing steps do not affect the race result.
    • Losing steps continue running and are not cancelled; their spans are marked skipped, and late failures do not create additional span updates.
    • Suspended and cancelled outcomes from the winning step are preserved.