fix(execution): stop the event buffer retaining a run-length backlog - #6229
fix(execution): stop the event buffer retaining a run-length backlog#6229waleedlatif1 wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Terminal stream semantics are tightened: terminal status lives on the writer ( On the workflow execute SSE route, if the replay buffer rejects a terminal event, the live client still gets SSE while Removes unused Reviewed by Cursor Bugbot for commit 7c396f7. Configure here. |
Greptile SummaryThe PR changes execution-event buffering to bound failed backlogs, split oversized batches, preserve terminal status across concurrent flushes, and record degraded terminal metadata for reconnecting clients.
Confidence Score: 5/5The PR appears safe to merge because no eligible blocking follow-up finding remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/execution/event-buffer.ts | Adds capped chunk flushing, bounded budget-failure handling, writer-scoped terminal state, and isolated terminal retries. |
| apps/sim/app/api/workflows/[id]/execute/route.ts | Persists terminal stream metadata when the terminal replay-buffer write fails after live delivery. |
| apps/sim/lib/execution/redis-budget.server.ts | Removes unused standalone reservation scripts while retaining shared budget limits and key construction. |
| apps/sim/lib/execution/event-buffer.test.ts | Adds coverage for budget rejection, chunk splitting, terminal retries, concurrent flushes, and failure reporting. |
| apps/sim/app/api/workflows/[id]/execute/route.async.test.ts | Verifies degraded terminal metadata is recorded when terminal buffering fails. |
Sequence Diagram
sequenceDiagram
participant Executor
participant Writer as Event Writer
participant Redis
participant Live as Live SSE Client
participant Replay as Reconnecting Client
Executor->>Writer: write events
Writer->>Writer: split pending events into capped chunks
Writer->>Redis: flush chunk with byte-budget check
alt Budget accepts chunk
Redis-->>Writer: persisted
else Budget rejects chunk
Redis-->>Writer: rejected
Writer->>Writer: drop rejected chunk and back off
end
Executor->>Writer: write terminal event and status
alt Terminal write succeeds
Writer->>Redis: atomically persist event and terminal status
else Terminal write fails
Executor->>Live: deliver terminal event live
Executor->>Redis: persist degraded terminal metadata
end
Replay->>Redis: read replay events and metadata
Redis-->>Replay: events plus authoritative terminal state
Reviews (4): Last reviewed commit: "fix(execution): stop the event buffer re..." | Re-trigger Greptile
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8bed4ae. Configure here.
|
@cursor review |
906c8ea to
412ab18
Compare
The Redis byte-budget branch in doFlush requeued the rejected batch and rethrew, skipping the MAX_PENDING_EVENTS trim every other failure path applies. The backlog then grew for the rest of the run and each retry re-serialized it, so a wide parallel fan-out could drive unbounded heap growth and stall the event loop. Drop rejected chunks instead of requeueing, pace retries through the existing backoff, and split batches that exceed the single-write cap so an oversized batch can make progress instead of stalling forever. Terminal status is now writer-scoped, since a concurrent scheduled flush can be the loop that drains the final chunk, and a terminal event whose batch was dropped is retried on its own rather than lost with it. Record terminal stream meta when the terminal event cannot be buffered, so reconnecting readers stop polling an active stream until their deadline. Drop the unused reserve/release budget helpers.
412ab18 to
7c396f7
Compare
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7c396f7. Configure here.
Summary
doFlush's Redis byte-budget branch requeued the rejected batch and rethrew, skipping theMAX_PENDING_EVENTStrim every other failure path applies — so the backlog grew for the rest of the run and each retry re-serialized the whole thing (O(n²)). A wide parallel fan-out could drive unbounded heap growth and stall the event loop.consecutiveFlushFailuresso the existing backoff actually engages — the old branch threw before the increment, so budget failures retried at the 15ms interval.writeTerminalreported success. A terminal event whose batch was dropped is retried on its own rather than lost with it.activestream until the poll deadline and then errored.reserveExecutionRedisBytes/releaseExecutionRedisBytes— zero callers repo-wide. Their TTL invariants are already pinned against the surviving flush script.Tradeoff
Dropped chunks leave an interior gap in the replay buffer.
readExecutionEventsStateonly signals leading truncation, so a reconnecting client silently misses those events (live SSE delivery is unaffected). Those bytes were never going to persist, so the alternative was retaining them forever. Only signal today is aDropped execution events…warn.Type of Change
Testing
Unit tests only — each new test verified to fail against the unfixed source before landing. Not yet exercised against a real Redis or a live run; the Lua is mocked in all tests.
Checklist