chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildBillingLimitResolveDedupeKey } from "~/v3/services/billingLimit/billingLimitConstants";
|
||||
import { classifyPendingBillingLimitResolveConvergeFailure } from "~/v3/services/billingLimit/billingLimitPendingResolveFailure.server";
|
||||
import { runPendingBillingLimitResolves } from "~/v3/services/billingLimit/billingLimitPendingResolveCoordinator.server";
|
||||
import type { PendingBillingLimitResolve } from "~/v3/services/billingLimit/billingLimitPendingResolve.types";
|
||||
|
||||
describe("billingLimitConvergeResolve", () => {
|
||||
it("builds a stable dedupe key from org id and resolvedAt", () => {
|
||||
expect(buildBillingLimitResolveDedupeKey("org_123", "2026-06-16T12:00:00.000Z")).toBe(
|
||||
"billing-limit-resolve:org_123:2026-06-16T12:00:00.000Z"
|
||||
);
|
||||
});
|
||||
|
||||
it("classifies converge failures for ops triage", () => {
|
||||
expect(classifyPendingBillingLimitResolveConvergeFailure("new_only")).toBe("cancel-failing");
|
||||
expect(classifyPendingBillingLimitResolveConvergeFailure("queue")).toBe("converge-failing");
|
||||
});
|
||||
});
|
||||
|
||||
describe("runPendingBillingLimitResolves", () => {
|
||||
const pending: PendingBillingLimitResolve = {
|
||||
organizationId: "org_123",
|
||||
resumeMode: "new_only",
|
||||
resolvedAt: "2026-06-17T12:00:00.000Z",
|
||||
};
|
||||
|
||||
it("keeps org pending and skips ack when converge throws (cancel-failing path)", async () => {
|
||||
const completeCalls: string[] = [];
|
||||
|
||||
const stillPending = await runPendingBillingLimitResolves([pending], {
|
||||
converge: async () => {
|
||||
throw new Error("bulk cancel failed");
|
||||
},
|
||||
complete: async (organizationId) => {
|
||||
completeCalls.push(organizationId);
|
||||
return { completed: true };
|
||||
},
|
||||
});
|
||||
|
||||
expect(stillPending).toEqual(new Set(["org_123"]));
|
||||
expect(completeCalls).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps org pending when converge succeeds but ack throws (ack-only path)", async () => {
|
||||
let convergeCalls = 0;
|
||||
let completeCalls = 0;
|
||||
|
||||
const stillPending = await runPendingBillingLimitResolves(
|
||||
[{ ...pending, resumeMode: "queue" }],
|
||||
{
|
||||
converge: async () => {
|
||||
convergeCalls += 1;
|
||||
},
|
||||
complete: async () => {
|
||||
completeCalls += 1;
|
||||
throw new Error("resolve-complete unavailable");
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(stillPending).toEqual(new Set(["org_123"]));
|
||||
expect(convergeCalls).toBe(1);
|
||||
expect(completeCalls).toBe(1);
|
||||
});
|
||||
|
||||
it("keeps org pending when ack returns completed: false", async () => {
|
||||
const stillPending = await runPendingBillingLimitResolves([pending], {
|
||||
converge: async () => undefined,
|
||||
complete: async () => ({ completed: false }),
|
||||
});
|
||||
|
||||
expect(stillPending).toEqual(new Set(["org_123"]));
|
||||
});
|
||||
|
||||
it("clears org from pending set when converge and ack both succeed", async () => {
|
||||
const stillPending = await runPendingBillingLimitResolves([pending], {
|
||||
converge: async () => undefined,
|
||||
complete: async () => ({ completed: true }),
|
||||
});
|
||||
|
||||
expect(stillPending).toEqual(new Set());
|
||||
});
|
||||
|
||||
it("retries ack on a later tick after a transient ack failure", async () => {
|
||||
let ackAttempts = 0;
|
||||
|
||||
const deps = {
|
||||
converge: async () => undefined,
|
||||
complete: async () => {
|
||||
ackAttempts += 1;
|
||||
if (ackAttempts === 1) {
|
||||
throw new Error("resolve-complete unavailable");
|
||||
}
|
||||
return { completed: true };
|
||||
},
|
||||
};
|
||||
|
||||
expect(await runPendingBillingLimitResolves([pending], deps)).toEqual(new Set(["org_123"]));
|
||||
expect(await runPendingBillingLimitResolves([pending], deps)).toEqual(new Set());
|
||||
expect(ackAttempts).toBe(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user