services/retl-runner/src/recovery-schedule.test.ts
Rama newjitsu · réplica de lectura del repositorio original.
import { describe, expect, it } from "vitest";
import { nextRecoveryCheck, RecoverySchedule } from "./recovery-schedule";
describe("provider recovery backoff", () => {
it("keeps worker generations increasing past 100 while capping only backoff", () => {
const first = nextRecoveryCheck("run", "revision", undefined, 0)!;
const next = RecoverySchedule.parse(nextRecoveryCheck("run", "revision", { ...first, attempt: 100 }, 1000));
expect(next.attempt).toBe(101);
expect(Date.parse(next.nextCheckAt) - 1000).toBe(60 * 60_000);
expect(nextRecoveryCheck("run", "revision", { ...first, attempt: 2147483647 }, 1000)).toBeUndefined();
});
it("waits 30 minutes, increases by 1.3, and caps intervals at an hour", () => {
let now = Date.parse("2026-09-16T00:00:00.000Z");
let previous: RecoverySchedule | undefined;
for (const minutes of [30, 39, 50.7, 60, 60]) {
const next = RecoverySchedule.parse(nextRecoveryCheck("run", "revision", previous, now));
expect(Date.parse(next.nextCheckAt) - now).toBe(minutes * 60_000);
expect(next.deadline).toBe("2026-09-18T00:00:00.000Z");
now = Date.parse(next.nextCheckAt);
previous = next;
}
});
it("schedules a final check at the deadline and never extends the 48-hour window", () => {
const first = nextRecoveryCheck("run", "revision", undefined, 0)!;
const deadline = Date.parse(first.deadline);
const last = nextRecoveryCheck("run", "revision", first, deadline - 1000)!;
expect(last.nextCheckAt).toBe(first.deadline);
expect(nextRecoveryCheck("run", "revision", last, deadline)).toBeUndefined();
expect(nextRecoveryCheck("run", "revision", last, deadline + 1)).toBeUndefined();
});
it("slows to two hours after day one and upgrades legacy schedules only once", () => {
const day = 24 * 60 * 60_000;
const legacy = {
runId: "run",
revision: "rev",
attempt: 25,
deadline: new Date(day).toISOString(),
nextCheckAt: new Date(day).toISOString(),
};
const next = nextRecoveryCheck("run", "rev", legacy, day)!;
expect(next.nextCheckAt).toBe(new Date(day + 2 * 60 * 60_000).toISOString());
expect(next.deadline).toBe(new Date(2 * day).toISOString());
expect(nextRecoveryCheck("run", "rev", next, 2 * day)).toBeUndefined();
});
});