test(worker): guard in-memory buffer reclaim#2951
Conversation
Add a focused regression test for re-yielding an in-flight SessionMessageBuffer message after resetClaimed without relying on a durable processing row. This guards the queue failure class observed in LIB-284 while current main uses the in-memory buffer path. Co-Authored-By: Paperclip <noreply@paperclip.ing>
Greptile SummaryThis PR adds a single regression test to lock down the
Confidence Score: 4/5Safe to merge — only a test file is added, no production code changes. The new test correctly exercises the resetClaimed re-yield path and the assertions are accurate. The one note is that idleTimeoutMs: 10_000 means a regressed resetClaimed would cause the test to block for 10 seconds before failing, whereas all other tests in the file use 25–30 ms timeouts for the same purpose. tests/services/worker/session-message-buffer.test.ts — the idle timeout value is worth revisiting. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant T as Test
participant B as SessionMessageBuffer
participant G as drain generator
T->>B: "drain sessionDbId=1"
T->>B: enqueue Read/tool-1
T->>G: iterator.next first
activate G
G->>B: "claimNext -> message claimed=true"
G-->>T: "done=false value=messageId"
deactivate G
T->>B: resetClaimed
Note over B: claimed=false signal emitted no listener
T->>G: iterator.next second
activate G
Note over G: resumes from yield loops to claimNext
G->>B: "claimNext -> same message claimed=true"
G-->>T: "done=false value=messageId"
deactivate G
T->>B: confirm messageId
Note over B: message removed getPendingCount=0
T->>G: controller.abort
%%{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 T as Test
participant B as SessionMessageBuffer
participant G as drain generator
T->>B: "drain sessionDbId=1"
T->>B: enqueue Read/tool-1
T->>G: iterator.next first
activate G
G->>B: "claimNext -> message claimed=true"
G-->>T: "done=false value=messageId"
deactivate G
T->>B: resetClaimed
Note over B: claimed=false signal emitted no listener
T->>G: iterator.next second
activate G
Note over G: resumes from yield loops to claimNext
G->>B: "claimNext -> same message claimed=true"
G-->>T: "done=false value=messageId"
deactivate G
T->>B: confirm messageId
Note over B: message removed getPendingCount=0
T->>G: controller.abort
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
tests/services/worker/session-message-buffer.test.ts:78-82
**Slow failure on regression** — `idleTimeoutMs: 10_000` means that if `resetClaimed` ever fails to un-claim the message, `second = await iterator.next()` will block for a full 10 seconds before the idle timeout fires and the generator exits with `done: true`. The test would then fail on `expect(second.done).toBe(false)`, but only after a 10-second hang. All other tests in this file use 25–30 ms idle timeouts with a matching `onIdleTimeout` callback; adopting the same pattern here keeps CI feedback fast.
Reviews (1): Last reviewed commit: "test(worker): cover in-memory buffer rec..." | Re-trigger Greptile |
| const iterator = buffer.drain({ | ||
| sessionDbId: 1, | ||
| signal: controller.signal, | ||
| idleTimeoutMs: 10_000, | ||
| }); |
There was a problem hiding this comment.
Slow failure on regression —
idleTimeoutMs: 10_000 means that if resetClaimed ever fails to un-claim the message, second = await iterator.next() will block for a full 10 seconds before the idle timeout fires and the generator exits with done: true. The test would then fail on expect(second.done).toBe(false), but only after a 10-second hang. All other tests in this file use 25–30 ms idle timeouts with a matching onIdleTimeout callback; adopting the same pattern here keeps CI feedback fast.
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/services/worker/session-message-buffer.test.ts
Line: 78-82
Comment:
**Slow failure on regression** — `idleTimeoutMs: 10_000` means that if `resetClaimed` ever fails to un-claim the message, `second = await iterator.next()` will block for a full 10 seconds before the idle timeout fires and the generator exits with `done: true`. The test would then fail on `expect(second.done).toBe(false)`, but only after a 10-second hang. All other tests in this file use 25–30 ms idle timeouts with a matching `onIdleTimeout` callback; adopting the same pattern here keeps CI feedback fast.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
SessionMessageBuffer.resetClaimed()re-yielding an in-flight message without requiring a durablepending_messages.status='processing'row.Context
The live Liberty box is running claude-mem plugin
v10.6.2, where the installed generated worker bundle still has the durable pending queue behavior. Upstreammain(v13.6.1) has already moved the worker to the in-memorySessionMessageBufferpath, which removes the cross-process orphanedprocessingrow failure mode. This PR keeps that behavior reviewable and locked down with a focused test instead of proposing a stale patch against the old generated bundle.Verification
/Users/alex/.bun/bin/bun test tests/services/worker/session-message-buffer.test.tsgit diff --checkNot done