From a8ae7ffecfb51642f59620f9f76cf94f11921d3d Mon Sep 17 00:00:00 2001 From: Krishna Vijay <228381532+im-kvijay@users.noreply.github.com> Date: Wed, 30 Sep 2026 00:50:24 -0700 Subject: [PATCH] fix(usage): Cursor account history loads about 4x faster The reader requested one page of account events at a time. Cursor caps a page at 1,000 events and takes about a second to answer one, so a busy account spent most of a minute here before Usage could show anything. Keep up to six pages requested ahead of the one being consumed. Pages are still consumed in page order, so the read ends as it did before, and any request still in flight is cancelled when it does. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../src/usage/cursorUsageReader.test.ts | 71 +++++++++++++++++++ apps/server/src/usage/cursorUsageReader.ts | 23 +++++- 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/apps/server/src/usage/cursorUsageReader.test.ts b/apps/server/src/usage/cursorUsageReader.test.ts index 4bfa647c0aff..3483db4e8db0 100644 --- a/apps/server/src/usage/cursorUsageReader.test.ts +++ b/apps/server/src/usage/cursorUsageReader.test.ts @@ -19,4 +19,75 @@ describe("readCursorAccountUsage", () => { error: "Allow Keychain access on the Mac running T3 Code, then refresh.", }); }); + + it("reads the pages behind the first together and keeps them in page order", async () => { + const accessToken = `header.${Buffer.from(JSON.stringify({ sub: "auth|demo" })).toString("base64url")}.signature`; + let inFlight = 0; + let mostInFlight = 0; + const result = await readCursorAccountUsage( + { kind: "keychain" }, + 0, + 1781000000000, + async (_url, init) => { + const page: number = JSON.parse(String(init.body)).page; + inFlight++; + mostInFlight = Math.max(mostInFlight, inFlight); + // Later pages answer first, so record order cannot come from arrival order. + for (let turn = page; turn < 9; turn++) await Promise.resolve(); + inFlight--; + return Response.json({ + totalUsageEventsCount: 8001, + usageEventsDisplay: Array.from({ length: page === 9 ? 1 : 1000 }, (_, index) => ({ + timestamp: String(1780000000000 + (page - 1) * 1000 + index), + model: "gpt-5", + tokenUsage: { inputTokens: 1 }, + })), + }); + }, + async () => accessToken, + ); + assert.isNull(result.error); + assert.strictEqual(mostInFlight, 6); + assert.deepStrictEqual( + result.records.map((record) => record.timestampMs), + Array.from({ length: 8001 }, (_, index) => 1780000000000 + index), + ); + }); + + it("ends like a page-by-page read when a page fails, leaving no request open", async () => { + const accessToken = `header.${Buffer.from(JSON.stringify({ sub: "auth|demo" })).toString("base64url")}.signature`; + const fullPage = { + totalUsageEventsCount: 8001, + usageEventsDisplay: Array.from({ length: 1000 }, () => ({ tokenUsage: null })), + }; + // Page 3 fails while the pages after it are still waiting on Cursor. + for (const [secondPage, error] of [ + [() => Response.json(fullPage), "Cursor account usage could not be read."], + [() => new Response(null, { status: 401 }), "Sign in to Cursor again to read account usage."], + ] as const) { + let open = 0; + const result = await readCursorAccountUsage( + { kind: "keychain" }, + 0, + 1781000000000, + (_url, init) => { + const page: number = JSON.parse(String(init.body)).page; + if (page === 1) return Promise.resolve(Response.json(fullPage)); + if (page === 2) return Promise.resolve(secondPage()); + if (page === 3) return Promise.reject(new Error("connection reset")); + open++; + return new Promise((_resolve, reject) => { + init.signal?.addEventListener("abort", () => { + open--; + reject(init.signal?.reason); + }); + }); + }, + async () => accessToken, + ); + assert.strictEqual(result.error, error); + assert.deepStrictEqual(result.records, []); + assert.strictEqual(open, 0); + } + }); }); diff --git a/apps/server/src/usage/cursorUsageReader.ts b/apps/server/src/usage/cursorUsageReader.ts index 573506d818a1..cba0b0b9c568 100644 --- a/apps/server/src/usage/cursorUsageReader.ts +++ b/apps/server/src/usage/cursorUsageReader.ts @@ -106,6 +106,7 @@ export async function readCursorAccountUsage( }; } let accountKey: string | null = null; + const cancel = new AbortController(); try { const payload = accessToken.split(".")[1]; const subject = object( @@ -117,14 +118,14 @@ export async function readCursorAccountUsage( accountKey = accountHash(subject); if (!Number.isFinite(sinceMs) || !Number.isFinite(endDate) || sinceMs < 0 || sinceMs > endDate) throw new Error("Invalid date window"); - const deadline = AbortSignal.timeout(60_000); + const deadline = AbortSignal.any([cancel.signal, AbortSignal.timeout(60_000)]); const records: UsageRecord[] = []; const occurrences = new Map(); const pages: unknown[][] = []; let completed = false; const pageSize = 1000; let total: number | undefined; - for (let page = 1; ; page++) { + const readPage = async (page: number) => { // A count can include overlapping page boundaries. Allow room to // reconcile them without imposing a fixed account-size limit. if (page > (total === undefined ? 1000 : Math.ceil(total / pageSize) * 2 + 1)) { @@ -181,6 +182,21 @@ export async function readCursorAccountUsage( throw new Error("Inconsistent account usage page"); } if (typeof count === "number") total = count; + return events; + }; + // Cursor caps a page at 1,000 events and takes about a second to answer one, so the pages + // the first one's count implies are requested up to six ahead and consumed in page order. + const ahead: ReturnType[] = []; + for (let page = 1; ; page++) { + while (ahead.length < Math.min(6, Math.ceil((total ?? 0) / pageSize) - page + 1)) { + const pending = readPage(page + ahead.length); + // Handled when its turn comes, or cancelled if the read ends first. + pending.catch(() => undefined); + ahead.push(pending); + } + const events = await (ahead.shift() ?? readPage(page)); + // A rejected login comes back as the finished result instead of a page. + if (!Array.isArray(events)) return events; pages.push(events); if (events.length < pageSize) { completed = true; @@ -268,5 +284,8 @@ export async function readCursorAccountUsage( missing: false, error: "Cursor account usage could not be read.", }; + } finally { + // An early exit leaves the pages requested ahead of it in flight. + cancel.abort(); } }