fix(dashboards): cancel in-flight tile stream on refresh - #76429
fix(dashboards): cancel in-flight tile stream on refresh#76429posthog[bot] wants to merge 2 commits into
Conversation
Nothing cancelled the SSE tile stream when a refresh started: `api.dashboards.streamTiles` returns a cancel function that `loadDashboardStreaming` discarded, and `abortAnyRunningQuery` only aborted the per-insight refresh controller. So a refresh could write fresh results, then the still-running initial stream would deliver a tile computed against the old filters a few seconds later, silently reverting it. `abortAnyRunningQuery` (called on refresh and on cancel) now also cancels the tile stream and bumps a generation counter that the stream's callbacks check before dispatching, so anything already in flight from a superseded stream is dropped. `receiveTileFromStream` now replaces a tile with a matching id instead of appending a duplicate. Generated-By: PostHog Code Task-Id: e37dda42-f084-46c4-b49c-ef6e4e848d7b
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
🤖 CI report
|
| Root | Eager (shipped) | Δ vs base | Budget |
|---|---|---|---|
entry (logged-out pages, app bootstrap)src/index.tsx |
1.25 MiB · 22 files | no change | ███░░░░░░░ 27.7% of 4.51 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
8.14 MiB · 3,035 files | 🔺 +467 B (+0.0%) | ████████░░ 83.8% of 9.71 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
Largest files eagerly shipped from src/index.tsx
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 762 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 285.6 KiB | ../node_modules/.pnpm/posthog-js@1.409.5/node_modules/posthog-js/dist/rrweb.js |
| 267.7 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 235.5 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 231.5 KiB | ../node_modules/.pnpm/posthog-js@1.409.5/node_modules/posthog-js/dist/module.js |
| 154.3 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.3 KiB | src/lib/api.ts |
| 94.7 KiB | ../packages/quill/packages/quill/dist/index.js |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Toolbar bundle — eager 2.19 MiB within budget
What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.
| Metric | Size | Δ vs base | Budget |
|---|---|---|---|
| Eager (shipped) entry + static imports |
2.19 MiB · 17 files | no change | ████░░░░░░ 38.3% of 5.72 MiB |
| Deferred (lazy) | 2.08 MiB · 33 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.1 KiB | no change | █░░░░░░░░░ 5.8% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 718.3 KiB | dist/toolbar/toolbar-app-FT4UJ3IP.css |
| 551.4 KiB | dist/toolbar/chunk-chunk-AGSGCCBT.js |
| 484.6 KiB | dist/toolbar/chunk-chunk-T44C2V5C.js |
| 133.6 KiB | dist/toolbar/chunk-chunk-KBLX73CM.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-T5KY5WYR.js |
| 71.0 KiB | dist/toolbar/toolbar-app-FKUW2FOM.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-27JL52RE.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-3JVI3ZTF.js |
| 20.9 KiB | dist/toolbar/chunk-chunk-HJ3ZJMTU.js |
| 12.2 KiB | dist/toolbar/chunk-chunk-PIK3PADE.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +9.3 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1381.31 MiB · 🔺 +9.3 KiB (+0.0%)
CI's typegen-drift check expects the generated action interface sorted alphabetically; the new tileStreamCancelled entry was placed after tileStreamingFailure instead of before tileStreamingComplete. Generated-By: PostHog Code Task-Id: e37dda42-f084-46c4-b49c-ef6e4e848d7b
Problem
api.dashboards.streamTiles(frontend/src/lib/api.ts) returns a cancel function thatloadDashboardStreaming(frontend/src/scenes/dashboard/dashboardLogic.tsx) discarded.abortAnyRunningQueryonly aborted the per-insight refreshAbortController, not the stream.receiveTileFromStreammerged whatever tile arrived with no ordering guard, appending duplicates rather than replacing.Changes
abortAnyRunningQuerynow also cancels the in-flight tile stream (stored oncache.cancelTileStream) and bumps a generation counter.onMessage/onComplete/onErrorcallbacks check that generation before dispatching, so anything already in flight from a superseded stream is dropped even if cancellation races with delivery.receiveTileFromStreamnow replaces a tile with a matching id instead of appending a duplicate entry.tileStreamCancelledaction flipsdashboardStreamingback tofalsewhen a stream is cancelled mid-flight, so the loading state doesn't get stuck.How did you test this code?
Added two cases to
dashboardLogic.test.ts:replaces an existing tile instead of appending a duplicate for the same tile id— catches the literal append-not-replace bug in the reducer.cancels the in-flight tile stream on refresh so a tile it delivers afterwards is dropped— mocksapi.dashboards.streamTiles, simulates a refresh mid-stream viaabortAnyRunningQuery, and asserts a late tile delivery is dropped. This is the actual reported regression.Both tests fail against the pre-fix code (verified) and pass with the fix. Ran the full
dashboardLogic.test.tssuite (91 passed) andpnpm --filter=@posthog/frontend typescript:check— no new errors introduced (remaining errors are pre-existing, unrelated to a missing@posthog/quillbuild).I could not manually reproduce the visual revert in a browser in this environment (no way to drive real SSE timing through the UI here), so this relies on the logic-level regression test above rather than a live repro.
Automatic notifications
Docs update
No docs affected — internal dashboard loading behavior, no user-facing API or workflow change.
🤖 Agent context
Autonomy: Fully autonomous
I (Claude Code) traced the bug from an inbox report combining a support ticket and a replay scan finding, both pointing at
dashboardLogic.tsx's tile streaming path. Checked for existing work first: searched open PRs/issues touchingdashboardLogic.tsxandstreamTiles— found related-but-different dashboard-race fixes (#69543, #68476, #76386, #69660) but none add stream cancellation or an ordering guard, so this is additive.Scoped the fix to the confirmed root cause (stream cancellation + ordering guard) rather than also touching the narrower non-streaming
loadDashboard/loadDashboardSuccessrace the report flagged as a related-but-unconfirmed variant.No repo skills were required beyond
/writing-tests(invoked before adding the regression tests).Created with PostHog Desktop from this inbox report.