Uh oh!
There was an error while loading. Please reload this page.
fix(tables): server-authoritative run badge, tail SSE from latest, harden Stop-all - #5492
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Run badge & API: Drops SSE: Fresh mounts connect without Header & cells: Stop-all / runs: Dispatch row is inserted before long prep so early Stop-all can cancel; Reviewed by Cursor Bugbot for commit a5a39a8. Bugbot is set up for automated code reviews on this repo. Configure here. |
Uh oh!
There was an error while loading. Please reload this page.
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |
Greptile SummaryThis PR replaces fragile per-event ±1 client-side run-count deltas with a server-authoritative throttled-refetch model and fixes the reload animation storm caused by replaying buffered SSE history over fresh DB state on mount.
Confidence Score: 5/5Safe to merge. The changes are well-reasoned rewrites of previously fragile client-side delta logic, and all edge cases are guarded. The throttled run-state refetch uses a dirty-flag follow-up so the badge cannot freeze; the prep failure try-catch always re-throws the original error; readDispatch post-prep correctly returns null to prevent firing the dispatcher for a cancelled dispatch; all previous review findings are addressed. No files require special attention — the API contract change is propagated through every consumer. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant C as Client
participant SQ as Dispatches API
participant SS as SSE Stream
participant DB as Database
Note over C,DB: Fresh mount
C->>SQ: GET /dispatches
SQ->>DB: countRunningCells + listActiveDispatches
DB-->>SQ: runningByRowId, hasRunning, dispatches
SQ-->>C: run-state snapshot
C->>SS: GET /events/stream (no from)
SS->>DB: getLatestTableEventId
DB-->>SS: latestId
SS-->>C: stream from latestId only
Note over C,DB: Cell events burst
SS-->>C: cell event N
C->>C: applyCell + scheduleDispatchInvalidate (leading)
C->>SQ: GET /dispatches (cancelRefetch false)
SQ-->>C: updated counts
SS-->>C: cell events N+1 to N+20
C->>C: trailing timer fires after 1s
C->>SQ: GET /dispatches
SQ-->>C: final counts
Note over C,DB: Stop-all
C->>C: cancelQueries + optimistic zero
C->>SQ: POST /cancel
SQ->>DB: markActiveDispatchesCancelled
SQ-->>C: 200 OK
C->>SQ: invalidateQueries onSettled
SQ-->>C: reconciled run-state
Note over C,DB: Reconnect after error
SS--xC: connection lost
C->>SS: "GET /events/stream?from=lastEventId"
SS-->>C: replay and resume
%%{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"}}}%%
sequenceDiagram
participant C as Client
participant SQ as Dispatches API
participant SS as SSE Stream
participant DB as Database
Note over C,DB: Fresh mount
C->>SQ: GET /dispatches
SQ->>DB: countRunningCells + listActiveDispatches
DB-->>SQ: runningByRowId, hasRunning, dispatches
SQ-->>C: run-state snapshot
C->>SS: GET /events/stream (no from)
SS->>DB: getLatestTableEventId
DB-->>SS: latestId
SS-->>C: stream from latestId only
Note over C,DB: Cell events burst
SS-->>C: cell event N
C->>C: applyCell + scheduleDispatchInvalidate (leading)
C->>SQ: GET /dispatches (cancelRefetch false)
SQ-->>C: updated counts
SS-->>C: cell events N+1 to N+20
C->>C: trailing timer fires after 1s
C->>SQ: GET /dispatches
SQ-->>C: final counts
Note over C,DB: Stop-all
C->>C: cancelQueries + optimistic zero
C->>SQ: POST /cancel
SQ->>DB: markActiveDispatchesCancelled
SQ-->>C: 200 OK
C->>SQ: invalidateQueries onSettled
SQ-->>C: reconciled run-state
Note over C,DB: Reconnect after error
SS--xC: connection lost
C->>SS: "GET /events/stream?from=lastEventId"
SS-->>C: replay and resume
Reviews (8): Last reviewed commit: "fix(tables): widen warm-cache remount ch..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…ck only on fetch start
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Greptile SummaryThis PR hardens the table run UI across three axes: badge accuracy, SSE mount behavior, and Stop-all reliability. The "X running" badge moves from fragile client-side ±1 cell deltas to a server-refetched snapshot throttled at 1 s with a dirty-flag follow-up to prevent freeze on slow fetches; optimistic bumps now cancel any in-flight query before writing to avoid stale responses clobbering the count.
Confidence Score: 4/5Safe to merge. The core data paths are server-authoritative now, tests cover the new event-buffer and contract shapes, and the Stop-all race condition fix is solid. The change is well-tested and the main logic — server-refetched badge, tail-from-latest SSE, dispatch-first insertion — is sound. The only noteworthy limitation is hasRunningCell: when the dispatcher's active batch has scrolled entirely out of the loaded viewport, the header flips back from 'N running' to 'Queueing' mid-run. This is called out in the PR description as an intentional tradeoff, but it is a visible inaccuracy in a scenario reachable with large tables. apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx (hasRunningCell limitation) and apps/sim/lib/table/workflow-columns.ts (readDispatch imported separately from other dispatcher functions). Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client
participant SSEHook as useTableEventStream
participant RQ as React Query Cache
participant Server as API / DB
Note over Client,Server: Fresh mount — tail from latest
Client->>Server: GET /dispatches (fetchTableRunState)
Server-->>RQ: "{ dispatches, runningByRowId }"
Client->>Server: GET /events/stream (no `from`)
Server->>Server: getLatestTableEventId()
Note over Server: lastEventId = N (no replay)
Server-->>SSEHook: stream starts at event N+1
Note over Client,Server: User clicks Run All
Client->>RQ: cancelQueries(activeDispatches)
Client->>RQ: setQueryData (optimistic bump)
Client->>Server: POST runWorkflowColumn
Server->>Server: insertDispatch (FIRST)
Server->>Server: cancelPriorRuns + bulkClear
Server->>Server: readDispatch (check not cancelled)
Server-->>Client: "{ dispatchId }"
Server-->>SSEHook: cell SSE events
SSEHook->>SSEHook: scheduleDispatchInvalidate (throttled)
SSEHook->>Server: GET /dispatches (refetch)
Server-->>RQ: updated runningByRowId
Note over Client,Server: User clicks Stop All
Client->>RQ: cancelQueries(activeDispatches)
Client->>RQ: setQueryData (optimistic zero)
Client->>Server: POST cancelTableRuns
Server->>Server: markActiveDispatchesCancelled
Server-->>SSEHook: dispatch cancelled SSE
SSEHook->>SSEHook: invalidateDispatchesNow (urgent)
Server-->>RQ: refetch on onSettled
%%{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"}}}%%
sequenceDiagram
participant Client
participant SSEHook as useTableEventStream
participant RQ as React Query Cache
participant Server as API / DB
Note over Client,Server: Fresh mount — tail from latest
Client->>Server: GET /dispatches (fetchTableRunState)
Server-->>RQ: "{ dispatches, runningByRowId }"
Client->>Server: GET /events/stream (no `from`)
Server->>Server: getLatestTableEventId()
Note over Server: lastEventId = N (no replay)
Server-->>SSEHook: stream starts at event N+1
Note over Client,Server: User clicks Run All
Client->>RQ: cancelQueries(activeDispatches)
Client->>RQ: setQueryData (optimistic bump)
Client->>Server: POST runWorkflowColumn
Server->>Server: insertDispatch (FIRST)
Server->>Server: cancelPriorRuns + bulkClear
Server->>Server: readDispatch (check not cancelled)
Server-->>Client: "{ dispatchId }"
Server-->>SSEHook: cell SSE events
SSEHook->>SSEHook: scheduleDispatchInvalidate (throttled)
SSEHook->>Server: GET /dispatches (refetch)
Server-->>RQ: updated runningByRowId
Note over Client,Server: User clicks Stop All
Client->>RQ: cancelQueries(activeDispatches)
Client->>RQ: setQueryData (optimistic zero)
Client->>Server: POST cancelTableRuns
Server->>Server: markActiveDispatchesCancelled
Server-->>SSEHook: dispatch cancelled SSE
SSEHook->>SSEHook: invalidateDispatchesNow (urgent)
Server-->>RQ: refetch on onSettled
|
…st on seq-read errors
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
… run resolves without a dispatch
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |
Uh oh!
There was an error while loading. Please reload this page.
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |
Uh oh!
There was an error while loading. Please reload this page.
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0c7e829. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
TheodoreSpeaks
commented
Jul 7, 2026
@greptile review |

Summary
runningCellCount; refetch the run-state snapshot on a leading+trailing 1s throttle as cell SSE events arrive (cancelRefetch: false+ dirty-flag follow-up so slow fetches can't livelock or strand a stale final count)countActiveRunCells' per-refetch rows-ahead COUNT deletedType of Change
Testing
Tested manually (run-all/stop-all cycles, reload mid-run, batch transitions). Added tests for the events buffer memory path, dispatches route shape, and the stream
fromparam. Full lint, type-check, check:api-validation:strict, check:react-query pass.Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_013d4zXsMMwVBmXk33JBok7d