fix(test): consume runtime-app-reload frames monotonically (#111) - #114
fix(test): consume runtime-app-reload frames monotonically (#111)#114ScriptedAlchemy wants to merge 3 commits into
Conversation
The overview e2e counted HMR frames exactly, so a late extra generation from an at-least-once reload (or a hashless compile treated as unique) failed 1-in-5 under load. Skip unidentifiable App hashes in the #73 channel and assert unique ordinals as a monotonic prefix instead.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e1423bf887
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const hash = stats.hash; | ||
| if (typeof hash !== 'string' || hash.length === 0) return; |
There was a problem hiding this comment.
Preserve reloads for successful hashless App builds
When Rsbuild reports a later successful App completion without a hash, this now returns before onAppReload(), even if that completion wrote changed App output. Hash absence prevents deduplication but does not establish that the build is unchanged, so under the same loaded conditions that produce hashless completions, the user-facing example can leave its iframe running stale assets indefinitely until another hashed App compilation occurs, contrary to this option's contract of notifying each later successful changed compilation. Retain a conservative reload or derive another reliable completion identity instead of silently dropping the event.
AGENTS.md reference: AGENTS.md:L10-L12
Useful? React with 👍 / 👎.
Unique-sorted ordinals are tautologically monotonic. Check the actual runtime-app-reload sequence is non-decreasing and include SSE hub sequence in the failure diagnostic.
A later successful App compile without stats.hash is unidentifiable, not unchanged. Skipping onAppReload left the example iframe stale. Dedupe hashed completions only; hashless success still notifies (at-least-once).
| expect(runtimePreviewHmrMessages).toEqual(hmrMessagesBeforeConfigReconcile); | ||
| expectMonotonicReloadFrames(); | ||
| const reloadOrdinals = ownedReloadOrdinals(); | ||
| expect(reloadOrdinals.slice(0, reloadOrdinalsBeforeConfigReconcile.length)).toEqual(reloadOrdinalsBeforeConfigReconcile); |
There was a problem hiding this comment.
[P2] Reject reload ordinals minted during config reconciliation
This prefix assertion allows arbitrary new ordinals after the saved prefix. If the two initial watched-source edits coalesce into generation 1, then a spurious reload caused by the later finite, invalid, or repaired config write can become generation 2 and this helper still passes. That weakens the prior contract that those reconciliations retain the existing preview without emitting another App reload. First wait for the edit-triggered sequence to settle, snapshot it, and require the sequence to remain exactly unchanged throughout the config-reconcile phase (while still tolerating duplicate frames for already-seen ordinals).
…ity (ported from #114) A hashless App completion fell back to the stats object as the dedupe key: every such completion compared unequal (always minting) and clobbered the retained hash, so the next unchanged hashed completion minted a spurious frame too. Hashless success still reloads (unidentifiable is not unchanged), but the retained hash survives it. Regression covers hashless/empty-hash minting and the unchanged-hash-after-hashless dedupe.
|
Reconciled with #120 (Wave 1 lane 0), which supersedes this PR for issue #111; closing per the owner's instruction (branch left intact). Adopted from this PR, with credit: the Not adopted: the overview e2e assertion shape. #120's captured failing sequence ( |
…ity (ported from #114) A hashless App completion fell back to the stats object as the dedupe key: every such completion compared unequal (always minting) and clobbered the retained hash, so the next unchanged hashed completion minted a spurious frame too. Hashless success still reloads (unidentifiable is not unchanged), but the retained hash survives it. Regression covers hashless/empty-hash minting and the unchanged-hash-after-hashless dedupe.
…ls in the overview e2e (#120) * fix(test): consume owned reload frames monotonically over generation ordinals Two replaced watched sources legitimately compile as one coalesced or two split App generations under load, so the overview e2e's exact frame-snapshot equality raced the second frame. Assert monotonic, duplicate-tolerant, budget-bounded generation consumption instead (issue #111, same shape as the dev-provider fix from #20). * fix(rsc-runtime-demo): never dedupe App reloads by stats object identity (ported from #114) A hashless App completion fell back to the stats object as the dedupe key: every such completion compared unequal (always minting) and clobbered the retained hash, so the next unchanged hashed completion minted a spurious frame too. Hashless success still reloads (unidentifiable is not unchanged), but the retained hash survives it. Regression covers hashless/empty-hash minting and the unchanged-hash-after-hashless dedupe.
Fixes #111
Problem
packages/workbench/tests/overview.e2e.test.ts(offers the host-owned MCP playground handoff...) failed intermittently with an extraruntime-app-reloadgeneration frame beyond the exact HMR message list it pinned. Reproduced 1-in-5 on unmodifiedmainunder Node 26, and it was the dominant local-ci gate tax.Captured green sequences on this machine were
[generation 0 (connect replay), generation 1 (changed App compile)]. A later generation-0 frame appears only after MCP playground handoff opens a second proxy socket. The flake is an extra frame of an already-seen or late ordinal landing between the post-edit snapshot and config-reconcile equality.Fix
Two complementary shapes, both required by the evidence:
dev-provider.integration.test.ts(emits one owned App reload...).{latestSequence, subscriptionCount}.Product contract is unchanged: one owned reload per later successful changed App compilation. Hashless compiles were never a proven generation.
Test plan
AGENT_BUNDLE_TEST_TIME_SCALE=4)/home/box/.local/node/currentand system v20.19.2)