fix: cache /data metrics for instant reload#901
Conversation
Use sessionStorage so a second reload in the same session paints instantly, and align the success-rate copy with the Capgo global_stats source. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughWalkthroughThe data page now describes Live Update reliability using the ChangesLive Update reliability
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant data.astro
participant sessionStorage
participant MetricsEndpoint
participant MetricsUI
data.astro->>sessionStorage: Read cached metrics
sessionStorage-->>data.astro: Return cached metrics or no entry
data.astro->>MetricsUI: Render cached metrics when available
data.astro->>MetricsEndpoint: Fetch fresh metrics with abort timeout
MetricsEndpoint-->>data.astro: Return raw metrics payload
data.astro->>sessionStorage: Store payload and timestamp
data.astro->>MetricsUI: Render normalized metrics or unavailable state
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_65f05e9a-92f7-4d41-9188-d12b21a788b7) |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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.
Inline comments:
In `@apps/web/src/pages/data.astro`:
- Line 38: Add an aria-live="polite" region to the success-rate KPI rendered in
the data page, preferably with aria-atomic="true", so updates made by
renderMetrics() are announced to screen readers while preserving the existing
value and data-kpi="success-rate" marker.
- Around line 315-316: Update the cache validation around parsed.savedAt in the
metrics cache parsing flow to capture the current time and reject entries whose
savedAt is later than that time, in addition to the existing type and TTL
checks. Only call normalizeMetrics for non-future, non-expired entries.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a6de520e-0a39-427b-862c-34b9ce4b3d84
📒 Files selected for processing (2)
.github/pr-assets/data-page-cache-global-stats.webpapps/web/src/pages/data.astro
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
|
|
||
| <div class="data-kpis" aria-label="Reliability summary"> | ||
| <div><p>30-day success rate</p><strong data-kpi="success-rate">—</strong></div> | ||
| <div><p>Success rate</p><strong data-kpi="success-rate">—</strong></div> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Announce the asynchronously populated success rate.
renderMetrics() replaces this value after cache and network loads, but it is not in a live region. Add aria-live="polite" (and preferably aria-atomic="true") so screen-reader users receive the KPI update.
Proposed fix
- <div><p>Success rate</p><strong data-kpi="success-rate">—</strong></div>
+ <div><p>Success rate</p><strong data-kpi="success-rate" aria-live="polite" aria-atomic="true">—</strong></div>As per coding guidelines, “Dynamic content must use aria-live regions for accessibility.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div><p>Success rate</p><strong data-kpi="success-rate">—</strong></div> | |
| <div><p>Success rate</p><strong data-kpi="success-rate" aria-live="polite" aria-atomic="true">—</strong></div> |
🤖 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 `@apps/web/src/pages/data.astro` at line 38, Add an aria-live="polite" region
to the success-rate KPI rendered in the data page, preferably with
aria-atomic="true", so updates made by renderMetrics() are announced to screen
readers while preserving the existing value and data-kpi="success-rate" marker.
Source: Coding guidelines
| if (typeof parsed.savedAt !== 'number' || Date.now() - parsed.savedAt > METRICS_CACHE_TTL_MS) return null | ||
| return normalizeMetrics(parsed.payload) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant file and inspect the metrics cache logic.
printf '\n== file list ==\n'
git ls-files 'apps/web/src/pages/data.astro' 'apps/web/src/**/config*' 'apps/web/src/**/*metrics*' | sed 's#^`#-` #'
printf '\n== relevant lines in apps/web/src/pages/data.astro ==\n'
nl -ba apps/web/src/pages/data.astro | sed -n '260,340p'
printf '\n== search for METRICS_CACHE_TTL_MS and savedAt usage ==\n'
rg -n "METRICS_CACHE_TTL_MS|savedAt|normalizeMetrics|cache" apps/web/src/pages/data.astro apps/web/src -g '!**/dist/**' -g '!**/build/**' || trueRepository: Cap-go/website
Length of output: 565
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== data.astro excerpt ==\n'
sed -n '280,340p' apps/web/src/pages/data.astro
printf '\n== savedAt / metrics cache references ==\n'
rg -n "savedAt|METRICS_CACHE_TTL_MS|normalizeMetrics|metrics cache|cache" apps/web/src/pages/data.astro apps/web/src -g '!**/dist/**' -g '!**/build/**' || trueRepository: Cap-go/website
Length of output: 50370
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '300,335p' apps/web/src/pages/data.astro
printf '\n--\n'
rg -n "savedAt|METRICS_CACHE_TTL_MS|normalizeMetrics" apps/web/src/pages/data.astroRepository: Cap-go/website
Length of output: 2069
Reject future-dated cache entries. savedAt values ahead of Date.now() bypass this TTL check, so stale metrics can be treated as fresh when revalidation fails. Add a savedAt <= now guard before accepting the cache.
🤖 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 `@apps/web/src/pages/data.astro` around lines 315 - 316, Update the cache
validation around parsed.savedAt in the metrics cache parsing flow to capture
the current time and reject entries whose savedAt is later than that time, in
addition to the existing type and TTL checks. Only call normalizeMetrics for
non-future, non-expired entries.
There was a problem hiding this comment.
1 issue found across 2 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/web/src/pages/data.astro">
<violation number="1" location="apps/web/src/pages/data.astro:34">
P3: Readers can no longer tell that each app/device/UTC-day combination is classified by its eventual install outcome, so the displayed success rate lacks its counting definition. Please retain that definition while naming `global_stats` as the source.
(Based on your team's feedback about naming the success combination.) [FEEDBACK_USED].</violation>
</file>
Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.
Fix all with cubic | Re-trigger cubic
| <h2 id="reliability-title">Daily success rate</h2> | ||
| </div> | ||
| <p>Counted per app, device, and UTC day. If that combination eventually installs successfully, it counts as success.</p> | ||
| <p>Success rate matches Capgo global_stats. Failure reasons stay deduplicated by app, device, and UTC day.</p> |
There was a problem hiding this comment.
P3: Readers can no longer tell that each app/device/UTC-day combination is classified by its eventual install outcome, so the displayed success rate lacks its counting definition. Please retain that definition while naming global_stats as the source.
(Based on your team's feedback about naming the success combination.) .
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/src/pages/data.astro, line 34:
<comment>Readers can no longer tell that each app/device/UTC-day combination is classified by its eventual install outcome, so the displayed success rate lacks its counting definition. Please retain that definition while naming `global_stats` as the source.
(Based on your team's feedback about naming the success combination.) .</comment>
<file context>
@@ -31,13 +31,13 @@ const content = {
<h2 id="reliability-title">Daily success rate</h2>
</div>
- <p>Counted per app, device, and UTC day. If that combination eventually installs successfully, it counts as success.</p>
+ <p>Success rate matches Capgo global_stats. Failure reasons stay deduplicated by app, device, and UTC day.</p>
</div>
</file context>
| <p>Success rate matches Capgo global_stats. Failure reasons stay deduplicated by app, device, and UTC day.</p> | |
| <p>Success rate matches Capgo global_stats: each app, device, and UTC-day combination counts as successful if it eventually installs successfully. Failure reasons use the same deduplication unit.</p> |
Keep the sessionStorage cache; drop visitor-facing global_stats wording that was not requested. Co-authored-by: Cursor <cursoragent@cursor.com>
|





Summary
sessionStorage(5 min TTL, stale-while-revalidate) so a second reload paints instantly.Backend success-rate source fix: Cap-go/capgo.app#2706.
Visual
Test plan
/data/, wait for metrics, reload — second load should show numbers immediatelyMade with Cursor