|
1 | | -import { beforeEach, describe, expect, test } from "vitest"; |
| 1 | +import { beforeEach, describe, expect, test, vi } from "vitest"; |
2 | 2 | import { |
3 | 3 | clearAgentRunContext, |
4 | 4 | emitAgentEvent, |
|
7 | 7 | registerAgentRunContext, |
8 | 8 | resetAgentEventsForTest, |
9 | 9 | resetAgentRunContextForTest, |
| 10 | + sweepStaleRunContexts, |
10 | 11 | } from "./agent-events.js"; |
11 | 12 |
|
12 | 13 | type AgentEventsModule = typeof import("./agent-events.js"); |
@@ -107,7 +108,7 @@ describe("agent-events sequencing", () => { |
107 | 108 | isHeartbeat: true, |
108 | 109 | }); |
109 | 110 |
|
110 | | - expect(getAgentRunContext("run-ctx")).toEqual({ |
| 111 | + expect(getAgentRunContext("run-ctx")).toMatchObject({ |
111 | 112 | sessionKey: "session-main", |
112 | 113 | verboseLevel: "full", |
113 | 114 | isHeartbeat: true, |
@@ -186,12 +187,48 @@ describe("agent-events sequencing", () => { |
186 | 187 |
|
187 | 188 | stop(); |
188 | 189 |
|
189 | | - expect(second.getAgentRunContext("run-dup")).toEqual({ sessionKey: "session-dup" }); |
| 190 | + expect(second.getAgentRunContext("run-dup")).toMatchObject({ sessionKey: "session-dup" }); |
190 | 191 | expect(seen).toEqual([ |
191 | 192 | { seq: 1, sessionKey: "session-dup" }, |
192 | 193 | { seq: 2, sessionKey: "session-dup" }, |
193 | 194 | ]); |
194 | 195 |
|
195 | 196 | first.resetAgentEventsForTest(); |
196 | 197 | }); |
| 198 | + |
| 199 | + test("sweeps stale run contexts and clears their sequence state", async () => { |
| 200 | + const stop = vi.spyOn(Date, "now"); |
| 201 | + stop.mockReturnValue(100); |
| 202 | + registerAgentRunContext("run-stale", { sessionKey: "session-stale", registeredAt: 100 }); |
| 203 | + registerAgentRunContext("run-active", { sessionKey: "session-active", registeredAt: 100 }); |
| 204 | + |
| 205 | + stop.mockReturnValue(200); |
| 206 | + emitAgentEvent({ runId: "run-stale", stream: "assistant", data: { text: "stale" } }); |
| 207 | + |
| 208 | + stop.mockReturnValue(900); |
| 209 | + emitAgentEvent({ runId: "run-active", stream: "assistant", data: { text: "active" } }); |
| 210 | + |
| 211 | + stop.mockReturnValue(1_000); |
| 212 | + expect(sweepStaleRunContexts(500)).toBe(1); |
| 213 | + expect(getAgentRunContext("run-stale")).toBeUndefined(); |
| 214 | + expect(getAgentRunContext("run-active")).toMatchObject({ sessionKey: "session-active" }); |
| 215 | + |
| 216 | + const seen: Array<{ runId: string; seq: number }> = []; |
| 217 | + const unsubscribe = onAgentEvent((evt) => { |
| 218 | + if (evt.runId === "run-stale" || evt.runId === "run-active") { |
| 219 | + seen.push({ runId: evt.runId, seq: evt.seq }); |
| 220 | + } |
| 221 | + }); |
| 222 | + |
| 223 | + emitAgentEvent({ runId: "run-stale", stream: "assistant", data: { text: "restarted" } }); |
| 224 | + emitAgentEvent({ runId: "run-active", stream: "assistant", data: { text: "continued" } }); |
| 225 | + |
| 226 | + unsubscribe(); |
| 227 | + stop.mockRestore(); |
| 228 | + |
| 229 | + expect(seen).toEqual([ |
| 230 | + { runId: "run-stale", seq: 1 }, |
| 231 | + { runId: "run-active", seq: 2 }, |
| 232 | + ]); |
| 233 | + }); |
197 | 234 | }); |
0 commit comments