Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions apps/server/src/provider/providerUsageLimits.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,35 @@ describe("applyUsageLimitsUpdate", () => {
).toBe(published);
});

it("keeps a failed probe marked when a sparse update lands on it", () => {
// A `rate_limit_event` names one window. Merged onto a failed probe it
// must not read as the full set, or a later failed probe keeps it as last-good.
const failed = {
checkedAt,
windows: [],
unavailable: { reason: "probeFailed" as const, message: "usage timed out" },
};
const next = applyUsageLimitsUpdate({
previous: failed,
checkedAt: "2026-09-03T12:00:05.000Z",
update: { windows: [weekly] },
});
expect(next).toEqual({
checkedAt: "2026-09-03T12:00:05.000Z",
windows: [weekly],
unavailable: failed.unavailable,
});
expect(
applyUsageLimitsUpdate({ previous: next, checkedAt, update: { windows: [weekly] } }),
).toBe(next);
});

it("marks a sparse update with no previous snapshot as probeFailed", () => {
expect(
applyUsageLimitsUpdate({ previous: undefined, checkedAt, update: { windows: [weekly] } }),
).toEqual({ checkedAt, windows: [weekly], unavailable: { reason: "probeFailed" } });
});

it("preserves reset credits when a streamed window update changes usage", () => {
const resetCredits = { availableCount: 2, nextExpiresAt: "2026-10-01T00:00:00.000Z" };
const next = applyUsageLimitsUpdate({
Expand All @@ -86,4 +115,14 @@ describe("resolveUsageLimitsAfterProbe", () => {
expect(resolveUsageLimitsAfterProbe({ published, probed: unsupported })).toBe(unsupported);
expect(resolveUsageLimitsAfterProbe({ published: undefined, probed: failed })).toBe(failed);
});

it("does not keep a probeFailed merge as last-good through a later failed probe", () => {
const failed = { checkedAt, windows: [], unavailable: { reason: "probeFailed" as const } };
const partial = applyUsageLimitsUpdate({
previous: failed,
checkedAt: "2026-09-03T12:00:05.000Z",
update: { windows: [weekly] },
});
expect(resolveUsageLimitsAfterProbe({ published: partial, probed: failed })).toBe(failed);
});
});
13 changes: 11 additions & 2 deletions apps/server/src/provider/providerUsageLimits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export function makeUnavailableUsageLimits(input: {
*
* An `unsupported` snapshot stays unsupported: an account that cannot have
* subscription windows will not start reporting them mid-turn.
*
* A `probeFailed` snapshot, or no snapshot at all, stays marked. The update
* is sparse by contract, so the windows it adds are not the full read; without
* the marker a lone weekly window would look complete and survive later failed
* probes as the last good set.
*/
export function applyUsageLimitsUpdate(input: {
readonly previous: ServerProviderUsageLimits | undefined;
Expand Down Expand Up @@ -88,12 +93,15 @@ export function applyUsageLimitsUpdate(input: {
changed = true;
}
}
if (!changed && previous !== undefined && previous.unavailable === undefined) {
if (!changed && previous !== undefined) {
return previous;
}
const unavailable =
previous === undefined ? { reason: "probeFailed" as const } : previous.unavailable;
return {
...makeUsageLimits({ checkedAt: input.checkedAt, windows: merged.values() }),
...(previous?.resetCredits !== undefined ? { resetCredits: previous.resetCredits } : {}),
...(unavailable !== undefined ? { unavailable } : {}),
};
}

Expand All @@ -112,7 +120,8 @@ function usageWindowEquals(a: ServerProviderUsageWindow, b: ServerProviderUsageW
* Choose what to publish after a status probe finishes. A probe that failed
* this time must not wipe bars a previous probe or a turn already
* established, so the last good snapshot stays; `unsupported` is
* authoritative and replaces them.
* authoritative and replaces them. A snapshot still marked `probeFailed` by a
* sparse merge is not last good and gives way to the probe's own result.
*
* A successful probe replaces the published windows outright, including any
* runtime update that landed while it was running. That is a deliberate
Expand Down