106 lines
2.7 KiB
TypeScript
106 lines
2.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
BOUNDED_POLLING_CEILINGS,
|
|
assertBoundedPollOperation,
|
|
definePollLeasePolicy,
|
|
type BoundedPollOperationContract,
|
|
} from "../../../src/application/policies/bounded-polling.ts";
|
|
|
|
const input = {
|
|
operationId: "GET_JOB_STATUS",
|
|
owner: "reference-job",
|
|
minimumIntervalMs: 5_000,
|
|
successIntervalMs: 10_000,
|
|
maxIntervalMs: 60_000,
|
|
maxAttempts: 5,
|
|
maxElapsedMs: 120_000,
|
|
maxResponseBytes: 16_384,
|
|
visibility: "VISIBLE_ONLY",
|
|
fallbackReason: "CONVERGENCE",
|
|
terminalStates: ["COMPLETED", "FAILED"],
|
|
} as const;
|
|
|
|
describe("bounded polling policy", () => {
|
|
it("copies and freezes a finite immutable lease", () => {
|
|
const terminalStates = ["COMPLETED", "FAILED"];
|
|
const policy = definePollLeasePolicy({
|
|
...input,
|
|
terminalStates,
|
|
});
|
|
terminalStates.push("CANCELLED");
|
|
|
|
expect(policy.terminalStates).toEqual(["COMPLETED", "FAILED"]);
|
|
expect(Object.isFrozen(policy)).toBe(true);
|
|
expect(Object.isFrozen(policy.terminalStates)).toBe(true);
|
|
});
|
|
|
|
it("rejects push-like cadence and unbounded convergence", () => {
|
|
expect(() =>
|
|
definePollLeasePolicy({
|
|
...input,
|
|
minimumIntervalMs: 4_999,
|
|
}),
|
|
).toThrow(TypeError);
|
|
expect(() =>
|
|
definePollLeasePolicy({
|
|
...input,
|
|
terminalStates: [],
|
|
}),
|
|
).toThrow(TypeError);
|
|
expect(() =>
|
|
definePollLeasePolicy({
|
|
...input,
|
|
maxAttempts: 121,
|
|
}),
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("admits only a one-request terminal replay-safe REST query", () => {
|
|
const policy = definePollLeasePolicy(input);
|
|
const operation: BoundedPollOperationContract = {
|
|
operationId: "GET_JOB_STATUS",
|
|
contractVersion: 2,
|
|
protocol: "REST",
|
|
semantics: "QUERY",
|
|
method: "GET",
|
|
replayPolicy: "SAFE",
|
|
retry: "never",
|
|
maxResponseBytes: 16_384,
|
|
transportMaxAttempts: 1,
|
|
authRecoveryCount: 0,
|
|
maxCumulativeSleepMs: 0,
|
|
serverStream: false,
|
|
};
|
|
|
|
expect(() =>
|
|
assertBoundedPollOperation(policy, operation),
|
|
).not.toThrow();
|
|
expect(() =>
|
|
assertBoundedPollOperation(policy, {
|
|
...operation,
|
|
transportMaxAttempts: 2 as 1,
|
|
}),
|
|
).toThrow(TypeError);
|
|
expect(() =>
|
|
assertBoundedPollOperation(policy, {
|
|
...operation,
|
|
maxResponseBytes: 8_192,
|
|
}),
|
|
).not.toThrow();
|
|
expect(() =>
|
|
assertBoundedPollOperation(policy, {
|
|
...operation,
|
|
maxResponseBytes: 0,
|
|
}),
|
|
).toThrow(TypeError);
|
|
expect(() =>
|
|
assertBoundedPollOperation(policy, {
|
|
...operation,
|
|
maxResponseBytes:
|
|
BOUNDED_POLLING_CEILINGS.maxResponseBytes + 1,
|
|
}),
|
|
).toThrow(TypeError);
|
|
});
|
|
});
|