fix: usage page fails while session cache refreshes (#105611)

* fix(gateway): preserve pending usage summaries

* chore: keep release notes in PR
This commit is contained in:
Peter Steinberger
2026-07-12 12:06:29 -07:00
committed by GitHub
parent c909a7e75d
commit d37d63c6ff
2 changed files with 14 additions and 5 deletions
@@ -284,7 +284,7 @@ describe("sessions.usage", () => {
expect(expectDefined(sessions[0], "sessions[0] test invariant").agentId).toBe("opus");
});
it("loads selected session summaries in one batched cache read and reports refresh status", async () => {
it("returns pending cache rows with null usage while refresh runs", async () => {
vi.mocked(discoverAllSessions).mockResolvedValueOnce([
{
sessionId: "s-a",
@@ -304,7 +304,10 @@ describe("sessions.usage", () => {
]);
vi.mocked(loadSessionCostSummariesFromCache).mockImplementation(async ({ sessions }) => ({
summaries: sessions.map((session) => {
const tokens = session.sessionId === "s-a" ? 10 : session.sessionId === "s-b" ? 20 : 30;
if (session.sessionId === "s-c") {
return null;
}
const tokens = session.sessionId === "s-a" ? 10 : 20;
return {
input: tokens,
output: 0,
@@ -339,7 +342,12 @@ describe("sessions.usage", () => {
};
expect(result.cacheStatus?.status).toBe("refreshing");
expect(result.sessions.map((session) => session.sessionId)).toEqual(["s-a", "s-b", "s-c"]);
expect(result.totals.totalTokens).toBe(60);
expect(result.sessions.map((session) => session.usage?.totalTokens ?? null)).toEqual([
10,
20,
null,
]);
expect(result.totals.totalTokens).toBe(30);
});
it("passes the requested timezone offset to session daily summaries", async () => {
+3 -2
View File
@@ -1445,7 +1445,8 @@ export const usageHandlers: GatewayRequestHandlers = {
for (const [entryIndex, merged] of mergedEntries.entries()) {
const agentId = merged.agentId;
const usage = usageByEntryIndex[entryIndex];
// A cold or stale cache intentionally yields null until its background refresh completes.
const usage = usageByEntryIndex[entryIndex] ?? null;
if (usage) {
addCostUsageTotals(aggregateTotals, usage);
@@ -1594,7 +1595,7 @@ export const usageHandlers: GatewayRequestHandlers = {
providerOverride: merged.storeEntry?.providerOverride,
modelProvider: merged.storeEntry?.modelProvider,
model: merged.storeEntry?.model,
usage: expectDefined(usage, "session usage summary"),
usage,
contextWeight: includeContextWeight
? (merged.storeEntry?.systemPromptReport ?? null)
: undefined,