diff --git a/src/agents/pi-embedded-runner/run/compaction-retry-aggregate-timeout.test.ts b/src/agents/pi-embedded-runner/run/compaction-retry-aggregate-timeout.test.ts index 5e1088c3155..2f2d7d0260c 100644 --- a/src/agents/pi-embedded-runner/run/compaction-retry-aggregate-timeout.test.ts +++ b/src/agents/pi-embedded-runner/run/compaction-retry-aggregate-timeout.test.ts @@ -1,6 +1,8 @@ import { describe, expect, it, vi } from "vitest"; import { waitForCompactionRetryWithAggregateTimeout } from "./compaction-retry-aggregate-timeout.js"; +type AggregateTimeoutParams = Parameters[0]; + async function withFakeTimers(run: () => Promise) { vi.useFakeTimers(); try { @@ -20,30 +22,38 @@ function expectClearedTimeoutState(onTimeout: ReturnType, timedOut expect(vi.getTimerCount()).toBe(0); } +function buildAggregateTimeoutParams( + overrides: Partial & + Pick, +): AggregateTimeoutParams & { onTimeout: ReturnType } { + const onTimeout = overrides.onTimeout ?? vi.fn(); + return { + waitForCompactionRetry: overrides.waitForCompactionRetry, + abortable: overrides.abortable ?? (async (promise) => await promise), + aggregateTimeoutMs: overrides.aggregateTimeoutMs ?? 60_000, + isCompactionStillInFlight: overrides.isCompactionStillInFlight, + onTimeout, + }; +} + describe("waitForCompactionRetryWithAggregateTimeout", () => { it("times out and fires callback when compaction retry never resolves", async () => { await withFakeTimers(async () => { - const onTimeout = vi.fn(); const waitForCompactionRetry = vi.fn(async () => await new Promise(() => {})); + const params = buildAggregateTimeoutParams({ waitForCompactionRetry }); - const resultPromise = waitForCompactionRetryWithAggregateTimeout({ - waitForCompactionRetry, - abortable: async (promise) => await promise, - aggregateTimeoutMs: 60_000, - onTimeout, - }); + const resultPromise = waitForCompactionRetryWithAggregateTimeout(params); await vi.advanceTimersByTimeAsync(60_000); const result = await resultPromise; expect(result.timedOut).toBe(true); - expectClearedTimeoutState(onTimeout, true); + expectClearedTimeoutState(params.onTimeout, true); }); }); it("keeps waiting while compaction remains in flight", async () => { await withFakeTimers(async () => { - const onTimeout = vi.fn(); let compactionInFlight = true; const waitForCompactionRetry = vi.fn( async () => @@ -54,62 +64,52 @@ describe("waitForCompactionRetryWithAggregateTimeout", () => { }, 170_000); }), ); - - const resultPromise = waitForCompactionRetryWithAggregateTimeout({ + const params = buildAggregateTimeoutParams({ waitForCompactionRetry, - abortable: async (promise) => await promise, - aggregateTimeoutMs: 60_000, - onTimeout, isCompactionStillInFlight: () => compactionInFlight, }); + const resultPromise = waitForCompactionRetryWithAggregateTimeout(params); + await vi.advanceTimersByTimeAsync(170_000); const result = await resultPromise; expect(result.timedOut).toBe(false); - expectClearedTimeoutState(onTimeout, false); + expectClearedTimeoutState(params.onTimeout, false); }); }); it("times out after an idle timeout window", async () => { await withFakeTimers(async () => { - const onTimeout = vi.fn(); let compactionInFlight = true; const waitForCompactionRetry = vi.fn(async () => await new Promise(() => {})); setTimeout(() => { compactionInFlight = false; }, 90_000); - - const resultPromise = waitForCompactionRetryWithAggregateTimeout({ + const params = buildAggregateTimeoutParams({ waitForCompactionRetry, - abortable: async (promise) => await promise, - aggregateTimeoutMs: 60_000, - onTimeout, isCompactionStillInFlight: () => compactionInFlight, }); + const resultPromise = waitForCompactionRetryWithAggregateTimeout(params); + await vi.advanceTimersByTimeAsync(120_000); const result = await resultPromise; expect(result.timedOut).toBe(true); - expectClearedTimeoutState(onTimeout, true); + expectClearedTimeoutState(params.onTimeout, true); }); }); it("does not time out when compaction retry resolves", async () => { await withFakeTimers(async () => { - const onTimeout = vi.fn(); const waitForCompactionRetry = vi.fn(async () => {}); + const params = buildAggregateTimeoutParams({ waitForCompactionRetry }); - const result = await waitForCompactionRetryWithAggregateTimeout({ - waitForCompactionRetry, - abortable: async (promise) => await promise, - aggregateTimeoutMs: 60_000, - onTimeout, - }); + const result = await waitForCompactionRetryWithAggregateTimeout(params); expect(result.timedOut).toBe(false); - expectClearedTimeoutState(onTimeout, false); + expectClearedTimeoutState(params.onTimeout, false); }); }); @@ -117,21 +117,17 @@ describe("waitForCompactionRetryWithAggregateTimeout", () => { await withFakeTimers(async () => { const abortError = new Error("aborted"); abortError.name = "AbortError"; - const onTimeout = vi.fn(); const waitForCompactionRetry = vi.fn(async () => await new Promise(() => {})); + const params = buildAggregateTimeoutParams({ + waitForCompactionRetry, + abortable: async () => { + throw abortError; + }, + }); - await expect( - waitForCompactionRetryWithAggregateTimeout({ - waitForCompactionRetry, - abortable: async () => { - throw abortError; - }, - aggregateTimeoutMs: 60_000, - onTimeout, - }), - ).rejects.toThrow("aborted"); + await expect(waitForCompactionRetryWithAggregateTimeout(params)).rejects.toThrow("aborted"); - expectClearedTimeoutState(onTimeout, false); + expectClearedTimeoutState(params.onTimeout, false); }); }); });