Skip to content

[rush-daemon] Fix summary writer racing early coalesced results (main is red) - #6095

Merged
Sean Larkin (TheLarkInn) merged 1 commit into
mainfrom
thelarkinn-fix-main-summary-race
Sep 25, 2026
Merged

Sean Larkin (TheLarkInn) merged 1 commit into
mainfrom
thelarkinn-fix-main-summary-race

Conversation

@TheLarkInn

Copy link
Copy Markdown
Member

Summary

main fails 3 @rushstack/rush-daemon tests with StdioSummarizer: The summary cannot be prepared until after close() is called. Two PRs that merged close together conflict at runtime, though not textually. This PR fixes that interaction, and both features keep working.

Fixed tests:

  • PhasedRequestBatching: "publishes an early failure result while the batch continues for other clients"
  • PhasedRequestBatching: "derives shared and disjoint failure results from each client subset"
  • DaemonRequestWirePhased: "merges two connections into one shared iteration with subset-specific results"

Root cause (#6068 × #6092)

Fix

#finishSettledEntry now publishes the early result through #produceEarlyResultAsync. That function yields one microtask (await Promise.resolve()) before calling #produceResultAsync. By then the notifying record has closed its summarizer, so the summary contains the full failure tail.

Ordering and per-client correctness don't change:

  • entry.finishPromise and the unsubscribe are still set synchronously. Other participants' #needsIteration checks and the batch's #finishEntryAsync (??=) still see the early result as claimed.
  • Once unsubscribed, the entry's sink can't receive events from other operations during the yield.
  • #produceResultAsync still flushes the sink before writing the result.

rush-lib is not changed.

Tests

  • The 3 tests above pass, and their assertions are unchanged.
  • New regression test in PhasedRequestSummary.test.ts: "writes the failure summary before an early result while the coalesced batch continues". Client A's selection fails early while client C's operation is held. The test asserts:
    • A's result arrives while the graph is still executing.
    • A's output has the FAILURE banner, the --[ FAILURE: … ]-- section containing the failed operation's output, the duration line, and Operations failed.
    • The result is A's last write.
    • C then succeeds with its own summary.
  • Without the fix, the regression test fails.

Linux validation (WSL Ubuntu-24.04, fresh clone of current main @ 7a0348d)

  • Before (pristine main): heft test in rush-daemon gave 422 passed, 3 failed (the 3 above).
  • After: rush build --to @rushstack/rush-daemon --to @rushstack/rush-cli-client (includes lint) passed, then rush test --only @rushstack/rush-daemon --only @rushstack/rush-cli-client:
    • rush-daemon: 426/426 passed
    • rush-cli-client: 275/275 passed

Optional follow-ups

  • In rush-lib, consider closing stdioSummarizer/problemCollector before finalizeOperation() notifies observers. Any onOperationCompleted observer could then read a finished report synchronously.

This came out of the automated rushd Linux analysis (Rushd Hive, bugs 15 and 38). It unblocks #6065, #6066 and #6069.

The early per-client result path (#6092) runs from onOperationCompleted, which the record's finalizeOperation() invokes synchronously before closing its StdioSummarizer. The summary writer (#6068) reads the failure tail from that summarizer, so it threw. Yield once before producing the early result.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The focused deferral correctly follows synchronous finalization ordering and has targeted regression coverage.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes a race where early coalesced results generated failure summaries before operation output summarizers closed.

Changes:

  • Defers early result generation by one microtask.
  • Adds regression coverage for complete early failure summaries.
  • Records a patch change for @rushstack/rush-daemon.
File Description
libraries/​rush-daemon/​src/​PhasedRequestRouter.ts Defers early summary generation until finalization completes.
libraries/​rush-daemon/​src/​test/​PhasedRequestSummary.test.ts Tests early failure summary completeness and ordering.
common/​changes/​@rushstack/​rush-daemon/​fix-main-summary-race_2026-09-24-21-45.json Adds the patch changelog entry.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@TheLarkInn
Sean Larkin (TheLarkInn) merged commit 3d690ab into main Sep 25, 2026
11 checks passed
@TheLarkInn
Sean Larkin (TheLarkInn) deleted the thelarkinn-fix-main-summary-race branch September 25, 2026 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Closed

Development

Successfully merging this pull request may close these issues.

5 participants