import { describe, expect, it } from "vitest"; import { calculateBackoff, parseRetryAfter, retryDelay, shouldRetry, } from "../../src/adapters/http/retry-policy.ts"; describe("HTTP retry policy", () => { it("uses capped exponential full jitter", () => { expect(calculateBackoff(0, () => 0.5)).toBe(125); expect(calculateBackoff(8, () => 1)).toBe(2_000); }); it("parses retry-after and chooses the longer bounded delay", () => { expect(parseRetryAfter("2", 0)).toBe(2_000); expect(retryDelay({ kind: "RATE_LIMITED", retryAfterMs: 500 }, 0, () => 0)).toBe( 500, ); }); it("allows at most two retries for safe or keyed requests", () => { const failure = { kind: "SERVER_FAILURE" }; expect(shouldRetry({ idempotency: "safe" }, failure, 0)).toBe(true); expect(shouldRetry({ idempotency: "keyed" }, failure, 1)).toBe(true); expect(shouldRetry({ idempotency: "safe" }, failure, 2)).toBe(false); expect(shouldRetry({ idempotency: "none" }, failure, 0)).toBe(false); expect( shouldRetry( { idempotency: "safe" }, { kind: "SERVER_FAILURE", httpStatus: 500 }, 0, ), ).toBe(false); }); it("does not automatically wait beyond 30 seconds", () => { expect( shouldRetry( { idempotency: "safe" }, { kind: "RATE_LIMITED", retryAfterMs: 31_000 }, 0, ), ).toBe(false); }); });