fix(cron): release cancelled embedded lanes

This commit is contained in:
Vincent Koc
2026-06-18 18:56:20 +08:00
committed by Vincent Koc
parent bf9c59b6a4
commit fa4f1abb29
7 changed files with 401 additions and 13 deletions

View File

@@ -543,6 +543,69 @@ describe("command queue", () => {
}
});
it("task timeout switches to a short abort grace period", async () => {
const lane = `timeout-abort-lane-${Date.now()}-${Math.random().toString(16).slice(2)}`;
setCommandLaneConcurrency(lane, 1);
vi.useFakeTimers();
try {
const abortController = new AbortController();
const first = enqueueCommandInLane(lane, async () => new Promise<never>(() => {}), {
taskTimeoutMs: 48 * 60 * 60 * 1000,
taskTimeoutAbortSignal: abortController.signal,
taskTimeoutAbortGraceMs: 25,
});
const firstRejected = expect(first).rejects.toBeInstanceOf(CommandLaneTaskTimeoutError);
let secondRan = false;
const second = enqueueCommandInLane(lane, async () => {
secondRan = true;
return "second";
});
abortController.abort();
await vi.advanceTimersByTimeAsync(24);
expect(secondRan).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await firstRejected;
await expect(second).resolves.toBe("second");
expect(secondRan).toBe(true);
} finally {
vi.useRealTimers();
}
});
it("task timeout release signal skips the abort grace period", async () => {
const lane = `timeout-release-lane-${Date.now()}-${Math.random().toString(16).slice(2)}`;
setCommandLaneConcurrency(lane, 1);
vi.useFakeTimers();
try {
const releaseController = new AbortController();
const first = enqueueCommandInLane(lane, async () => new Promise<never>(() => {}), {
taskTimeoutMs: 48 * 60 * 60 * 1000,
taskTimeoutProgressAtMs: () => Date.now(),
taskTimeoutAbortGraceMs: 25,
taskTimeoutReleaseSignal: releaseController.signal,
});
const firstRejected = expect(first).rejects.toBeInstanceOf(CommandLaneTaskTimeoutError);
let secondRan = false;
const second = enqueueCommandInLane(lane, async () => {
secondRan = true;
return "second";
});
releaseController.abort();
await vi.advanceTimersByTimeAsync(0);
await firstRejected;
await expect(second).resolves.toBe("second");
expect(secondRan).toBe(true);
} finally {
vi.useRealTimers();
}
});
it("task timeout falls back when progress timestamp callback throws", async () => {
const lane = `timeout-progress-throw-lane-${Date.now()}-${Math.random().toString(16).slice(2)}`;
setCommandLaneConcurrency(lane, 1);