|
1 | 1 | import { afterEach, describe, expect, it, vi } from "vitest"; |
2 | 2 | import type { HealthSummary } from "../commands/health.js"; |
3 | 3 | import type { ChatAbortControllerEntry } from "./chat-abort.js"; |
| 4 | +import { DEDUPE_MAX } from "./server-constants.js"; |
4 | 5 | |
5 | 6 | const cleanOldMediaMock = vi.fn(async () => {}); |
6 | 7 | |
@@ -222,4 +223,31 @@ describe("startGatewayMaintenanceTimers", () => {
|
222 | 223 | |
223 | 224 | stopMaintenanceTimers(timers); |
224 | 225 | }); |
| 226 | + |
| 227 | +it("evicts dedupe overflow by oldest timestamp even after reinsertion", async () => { |
| 228 | +vi.useFakeTimers(); |
| 229 | +vi.setSystemTime(new Date("2026-03-22T00:00:00Z")); |
| 230 | +const { startGatewayMaintenanceTimers } = await import("./server-maintenance.js"); |
| 231 | +const deps = createMaintenanceTimerDeps(); |
| 232 | +const now = Date.now(); |
| 233 | + |
| 234 | +for (let index = 0; index < DEDUPE_MAX; index += 1) { |
| 235 | +deps.dedupe.set(`stable-${index}`, { ts: now - 1_000 + index, ok: true }); |
| 236 | +} |
| 237 | + |
| 238 | +deps.dedupe.delete("stable-10"); |
| 239 | +deps.dedupe.set("stable-10", { ts: now - 2_000, ok: true }); |
| 240 | +deps.dedupe.set("overflow-newest", { ts: now - 100, ok: true }); |
| 241 | + |
| 242 | +const timers = startGatewayMaintenanceTimers(deps); |
| 243 | + |
| 244 | +await vi.advanceTimersByTimeAsync(60_000); |
| 245 | + |
| 246 | +expect(deps.dedupe.size).toBe(DEDUPE_MAX); |
| 247 | +expect(deps.dedupe.has("stable-10")).toBe(false); |
| 248 | +expect(deps.dedupe.has("stable-0")).toBe(true); |
| 249 | +expect(deps.dedupe.has("overflow-newest")).toBe(true); |
| 250 | + |
| 251 | +stopMaintenanceTimers(timers); |
| 252 | +}); |
225 | 253 | }); |