Skip to content

fix(trpc): raise leaderboard publish row caps so heavy days can publish - #6908

Open
hairez wants to merge 1 commit into
superset-sh:mainfrom
hairez:fix/leaderboard-publish-caps
Open

fix(trpc): raise leaderboard publish row caps so heavy days can publish#6908
hairez wants to merge 1 commit into
superset-sh:mainfrom
hairez:fix/leaderboard-publish-caps

Conversation

@hairez

@hairez hairez commented Aug 27, 2026

Copy link
Copy Markdown

What & why

A single oversized row rejects an entire leaderboard publish, so heavy users stop publishing without noticing.

The caps in publishSchema sit on the procedure input, which means zod fails the whole days array when one element is out of range and the mutation never reaches the handler. Every other day in that payload is dropped with it:

[leaderboard] auto-publish failed (will retry): TRPCClientError:
  days[4].cachedInput   Too big: expected number to be <=50000000000
  days[32].usdEstimate  Too big: expected number to be <=10000

They are also below real usage. cachedInput counts cache reads, which scale with session concurrency, so one model on one day of heavily parallel agent work clears the token cap and the $10,000 estimate together. usdEstimate is notional list price, not billed spend.

This raises the two caps so those days validate. 1T per field per row leaves about an order of magnitude over the largest row I have observed in practice, and $1M stays two orders of magnitude under the numeric(14,6) column the per-row value lands in.

Worth flagging for review, since I do not think the cap can carry the guarantee its comment claims: the rollup on leaderboard_participants is read back through bigint({ mode: "number" }), so the real ceiling is 2^53, and rows accumulate without bound across days, models and hosts. 1T x 9,007 rows reaches 2^53; the old 50B allowed 180,143. Neither is an invariant. If you want one it belongs in the rollup read path rather than in an input cap, and I am happy to do that instead if you would rather go that way.

Two related problems are out of scope here, but they are what turns this from an error into silent data loss, so they are worth their own fix:

  • The rejection is console-only after the join toast, so an account can sit broken indefinitely with no signal.
  • Days already rejected cannot be repaired. Once publishWindowDays shrinks the window back to 2 days nothing revisits them, and leaving and rejoining re-backfills only 30 days. Raising the caps fixes new publishes, not history.

Reported in Discord: https://discord.com/channels/1446776342577283114/1446776344204677132/1542510608828862515

How I tested it

  • Replayed a real 30-day payload from my own host against both versions of the schema, importing packages/trpc/src/router/leaderboard/schema.ts unmodified from main and from this branch. On main, 7 of 80 rows fail and publishSchema.safeParse rejects the whole payload with the same Too big messages as the console error above. On this branch all 80 rows parse and the payload is accepted.
  • bun run lint passes repo-wide: 6,615 files checked, no diagnostics.
  • bun run typecheck passes: 37 of 37 turbo tasks successful. Run locally with bun 1.4.0 rather than the pinned 1.3.14, so treat it as a strong signal rather than a CI-equivalent one.
  • I have not run bun run test. The change is two numeric literals and a comment, and neither constant is referenced anywhere else in the repo.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass (CI fails on lint warnings too)
  • "Allow edits from maintainers" is checked on fork PRs

The caps in publishSchema sit on the procedure input, so zod fails the whole days array when one element is out of range and the mutation never reaches the handler. Every other day in that payload is dropped with it.

cachedInput counts cache reads, which scale with session concurrency, so one model on one day of heavily parallel agent work clears both the 50B token cap and the $10,000 estimate together.
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f8da82c-2afe-4a19-80ce-6a895bd5ab00

📥 Commits

Reviewing files that changed from the base of the PR and between ff3f3d1 and 747fb6b.

📒 Files selected for processing (1)
  • packages/trpc/src/router/leaderboard/schema.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The leaderboard schema increases the maximum tokens per row to 1 trillion and the maximum USD value per row to 1 million. The associated comments now describe the applicable numeric constraints.

Changes

Leaderboard validation bounds

Layer / File(s) Summary
Raise leaderboard row limits
packages/trpc/src/router/leaderboard/schema.ts
MAX_TOKENS_PER_ROW_FIELD increases to 1 trillion. MAX_USD_PER_ROW increases to 1 million. Comments document the JavaScript number and numeric(14,6) constraints.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Merge Risk: 🔵 Low · up to 747fb

This change allows heavy leaderboard days to publish, but accumulated values can exceed the exact integer range used for leaderboard totals and tier calculations, potentially causing inaccurate displayed results. The PR is mergeable with explicit owner awareness and follow-up to make aggregate handling bigint-safe.

Suggested reviewers: harshithmullapudi

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title uses conventional commit format and clearly describes the primary change: raising leaderboard publish row caps.
Description check ✅ Passed The description explains the problem, the implementation, testing results, checklist status, and related out-of-scope issues. It provides sufficient context for review.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1 files.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@harshithmullapudi

harshithmullapudi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

hey, direction's right, and the two things you scoped out are the real damage - let's land this.

One ask before merging: everything so far shows the schema rejects those rows, not that the numbers are correct, and raising the cap publishes them to a public board. Two checks:

// bun run check.ts
import { computeLeaderboardPayload } from "./packages/host-service/src/trpc/router/usage/history/leaderboard-days";

const { days } = await computeLeaderboardPayload(30);
for (const d of [...days].sort((a, b) => b.cachedInput - a.cachedInput).slice(0, 10)) {
  console.log(d.day, d.provider, d.model, {
    cachedInput: d.cachedInput,
    sessions: d.sessions,
    approximate: d.approximate,
    readsPerOutput: Math.round(d.cachedInput / Math.max(1, d.output)),
  });
}

approximate: true means the model id missed the pricing table; readsPerOutput should sit in the low hundreds, and thousands would mean cache reads counted twice. Then npx ccusage@latest daily on those same days — our Claude parser was verified token-exact against it, so if it agrees the data is real and we can merge.

Small correction: 1T x 9,007 treats a row as one field, but tokens is the 5-field sum (leaderboard.ts:529-534) and that's what recomputeTotals rolls up. So ~1,800 rows, and the old cap allowed ~36,000. Doesn't change your point, but 1,800 is one publish away since model is free-form.

And yes - please move the guarantee into the rollup read path here. Once Number() is off the bigint sums (queries.ts:93, :230) the cap only has to be plausible, not load-bearing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants