fix(dashboard): keep extension progress polls single-flight - #3065
Open
tang-vu wants to merge 2 commits into
Open
fix(dashboard): keep extension progress polls single-flight#3065tang-vu wants to merge 2 commits into
tang-vu wants to merge 2 commits into
Conversation
This was referenced Aug 23, 2026
Contributor
Author
|
Batch compatibility receipt (2026-08-24) Built the inspectable synthetic branch
No manual merge resolution was required, including the shared Combined validation:
The stale Browserslist notice and authentication-dependent Phase C skips are unchanged environmental disclosures. #2903 remains draft because synthetic compatibility does not replace its declared live host-agent lifecycle gate and independent human review. |
This was referenced Aug 23, 2026
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.
Why this matters
The Extensions page polls installation progress every 3 seconds, while each request is allowed to run for up to 8 seconds. Its logs modal has a second 5-second progress interval with the same timeout. On a slow or restarting dashboard-api, either loop could therefore issue multiple progress requests before its previous request settled. Those requests independently update recovery counts, refresh catalog/terminal state, or update modal state, so one slow response can cause request amplification, premature connection-lost state, duplicate terminal handling, and stale UI writes.
These paths are reachable whenever a user installs/enables an extension, reloads during
installing/setting_up, or opens an extension's Logs modal.Root cause and invariant
Root cause:
activePollersprevented duplicate interval creation per service but did not prevent later async ticks from overlapping. The modal interval had no in-flight guard either.Invariant: each progress polling loop has at most one request in flight; different extensions remain independently pollable, and each loop resumes on the first scheduled tick after its pending request settles.
What changed
Overlap check
Searched open and closed PRs for extension install/progress polling,
activePollers, overlapping polls, and scanned all open PRs changingExtensions.jsx.upstream/main.Focused validation
Red/green reproductions:
npx vitest run src/pages/Extensions.test.jsx -t "progress polling single-flight"? 2 passed.Affected dashboard gate:
npm test -- --run? 28 files, 260 tests passednpm run lint? passednpm run build? passed (only the existing stale Browserslist data notice)git diff --check? passed (Git emitted only Windows LF/CRLF checkout notices)The tests prove browser scheduling and fetch concurrency at the rendered page and modal boundaries. They do not simulate a live extension image pull or dashboard-api restart.
Design, compatibility, and rollback
The per-service page guard preserves concurrent installs of different extensions; the modal-local guard does not couple modal work to the parent loop. Existing cadences, timeout, recovery tracker, and terminal state machine stay intact. Missed ticks are skipped rather than queued so a slow backend cannot accumulate work; the next normal tick retries after settlement.
Rollback is a normal revert of the two commits and restores overlapping requests whenever response latency exceeds an interval.