fix: stop dashboard refresh loops - #1621
Conversation
|
Warning Review limit reached
More reviews will be available in 5 minutes. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughService worker cache-first strategy replaced with network-first for built assets (under ChangesBlank Page Prevention via Asset Revalidation and Reload Suppression
🎯 3 (Moderate) | ⏱️ ~22 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/dashboard/app/__tests__/pwa.test.ts (1)
121-124: ⚡ Quick winCover the
fontdestination in this built-asset contract test.The production branch includes
request.destination === "font", but this regression guard currently validates only script/style.Suggested patch
expect(swSource).toContain('request.destination === "script"'); expect(swSource).toContain('request.destination === "style"'); + expect(swSource).toContain('request.destination === "font"'); expect(swSource).toContain('if (isBuiltAssetRequest) {');🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/dashboard/app/__tests__/pwa.test.ts` around lines 121 - 124, The test in packages/dashboard/app/__tests__/pwa.test.ts is asserting the built-asset contract against swSource but only checks for script/style destinations; update the assertions to also require the font destination by adding an expectation that swSource contains the string 'request.destination === "font"'. Keep the other checks (e.g., 'url.pathname.startsWith("/assets/")' and 'if (isBuiltAssetRequest) {') unchanged so the test still validates the built-asset request handling logic in the service worker.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/dashboard/app/__tests__/pwa.test.ts`:
- Around line 121-124: The test in packages/dashboard/app/__tests__/pwa.test.ts
is asserting the built-asset contract against swSource but only checks for
script/style destinations; update the assertions to also require the font
destination by adding an expectation that swSource contains the string
'request.destination === "font"'. Keep the other checks (e.g.,
'url.pathname.startsWith("/assets/")' and 'if (isBuiltAssetRequest) {')
unchanged so the test still validates the built-asset request handling logic in
the service worker.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ac41d34d-5589-4b38-ad9f-d79bc0305189
📒 Files selected for processing (5)
.changeset/fn-blank-page-service-worker-assets.mdpackages/dashboard/app/__tests__/pwa.test.tspackages/dashboard/app/__tests__/versionCheck.test.tspackages/dashboard/app/public/sw.jspackages/dashboard/app/versionCheck.ts
Greptile SummaryThis PR addresses two dashboard refresh-loop bugs: the service worker now uses network-first for built assets to prevent stale cached JS/CSS from surviving a rebuild, and the version checker no longer poisons the
Confidence Score: 5/5Safe to merge — both changes are narrowly scoped fixes with no correctness regressions in the primary paths. The service-worker change is a straightforward strategy swap backed by a version-bump and matching test update. The versionCheck fix correctly guards setReloadedRemoteVersion behind the same RELOAD_FLAG check used inside reloadOnce, so all three cases (flag set, auto-reload disabled, normal reload) are handled correctly. No logic errors or broken contracts were found in the changed code. versionCheck.ts — the new alreadyAttempted guard at line 243 has no dedicated test for the specific race window it closes. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[checkVersion called] --> B{version match?}
B -- yes --> C[clearReloadedRemoteVersion\nexit]
B -- no --> D{same mismatch\nas last check?}
D -- no --> E[record mismatch-pending\nexit]
D -- yes --> F{getReloadedRemoteVersion\n=== remote?}
F -- yes --> G[reload-suppressed trace\nexit]
F -- no --> H{RELOAD_FLAG\nalready set?}
H -- yes: alreadyAttempted=true --> I[skip setReloadedRemoteVersion]
H -- no: alreadyAttempted=false --> J{autoReloadEnabled?}
J -- yes --> K[setReloadedRemoteVersion\nremote]
J -- no --> L[skip setReloadedRemoteVersion]
K --> M[reloadOnce]
I --> M
L --> M
M --> N{RELOAD_FLAG set?}
N -- yes --> O[suppress reload\nwarn log]
N -- no --> P[set RELOAD_FLAG\ncall location.reload]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[checkVersion called] --> B{version match?}
B -- yes --> C[clearReloadedRemoteVersion\nexit]
B -- no --> D{same mismatch\nas last check?}
D -- no --> E[record mismatch-pending\nexit]
D -- yes --> F{getReloadedRemoteVersion\n=== remote?}
F -- yes --> G[reload-suppressed trace\nexit]
F -- no --> H{RELOAD_FLAG\nalready set?}
H -- yes: alreadyAttempted=true --> I[skip setReloadedRemoteVersion]
H -- no: alreadyAttempted=false --> J{autoReloadEnabled?}
J -- yes --> K[setReloadedRemoteVersion\nremote]
J -- no --> L[skip setReloadedRemoteVersion]
K --> M[reloadOnce]
I --> M
L --> M
M --> N{RELOAD_FLAG set?}
N -- yes --> O[suppress reload\nwarn log]
N -- no --> P[set RELOAD_FLAG\ncall location.reload]
Reviews (2): Last reviewed commit: "fix(review): changeset frontmatter, relo..." | Re-trigger Greptile |
|
Ready to review this PR? Stage has broken it down into 3 individual chapters for you:
Chapters generated by Stage for commit 7ddb3ef on Jun 21, 2026 7:15am UTC. |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
- Add required `---` frontmatter fences to the changeset so the changesets CLI picks it up during release (greptile P1). - Mark the remote version as reloaded only when a reload actually proceeds, so a pre-existing RELOAD_FLAG no longer permanently suppresses future reloads for that version (greptile P2). - Bump service-worker cache to v5 after merging main's v4 and update the pwa test assertions accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
073eb0f to
7ddb3ef
Compare
Summary
Returning to an existing dashboard tab no longer risks a blank page or a repeated refresh loop after a rebuild. Built assets now revalidate against the running server before falling back to service-worker cache, so stale JS/CSS cannot keep an old app shell alive.
The version checker also remembers which remote build it already auto-reloaded for. If focus or visibility events keep seeing the same remote build from an old bundle, Fusion suppresses repeat reloads instead of refreshing every time the browser regains focus.
Verification
pnpm --filter @fusion/dashboard exec vitest run --project dashboard-app app/__tests__/versionCheck.test.ts app/__tests__/pwa.test.tspnpm --filter @fusion/dashboard buildSummary by CodeRabbit
New Features
Bug Fixes