Skip to content

db: add coderouter account usage cache columns ahead of their reader - #14073

Merged
teamleaderleo merged 1 commit into
mainfrom
db/coderouter-usage-cache-columns
Sep 24, 2026
Merged

teamleaderleo merged 1 commit into
mainfrom
db/coderouter-usage-cache-columns

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds the four nullable columns #13978 stores coderouter quota readings in (usage, usage_error, usage_fetched_at, usage_refresh_claimed_at on coderouter_accounts). This is the migration only: no schema or code change.

It is split out because merging #13978 as one PR would break cr status in production for a while. The Vercel build doesn't run migrations, and cloud-vm-migrate.yml applies production migrations from main, so the reader would deploy before its columns existed. The order is now: merge this, run cloud-vm-migrate.yml against staging and then production, then merge #13978. The migration file is byte-identical to #13978's, so #13978's diff drops it once this is on main.

web/db/schema.ts is deliberately left out. Drizzle's select() without explicit fields reads every declared column, so declaring them before production has them would fail existing queries. #13978 declares them.

Risk: four ADD COLUMNs, all nullable, no default, no backfill; the ALTER takes only a brief lock.

Testing

Demo Video

Not applicable: database migration only.

Checklist

  • I tested the change locally (CI applies it)
  • I added or updated tests for behavior changes (not applicable, no behavior)
  • I updated docs/changelog if needed (not needed)
  • I requested bot reviews after my latest commit
  • All code review bot comments are resolved
  • All human review comments are resolved

— Ibex g1 🌿

🤖 Generated with Claude Code


Summary by cubic

Adds four nullable columns to coderouter_accounts to store coderouter quota readings (usage, usage_error, usage_fetched_at, usage_refresh_claimed_at). This is migration only; no code reads the columns yet.

Split out from #13978 (which adds the reader) because shipping them together would break cr status in production: Vercel builds don't run migrations, and production migrations are applied from main, so the reader would deploy before its columns exist. Merge order is this PR, then run cloud-vm-migrate.yml against staging and production, then #13978 (its copy is byte-identical, so it drops this file once this lands on main).

  • web/db/schema.ts is deliberately left out: Drizzle's select() without explicit fields reads every declared column, so declaring them before production has them would fail existing queries. coderouter: serve stored usage in account status #13978 declares them.
  • All four columns are nullable with no default and no backfill; the ALTER takes only a brief lock.

Written for commit 95364df. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added account usage tracking, including when usage data was last fetched and when a refresh was claimed.

Four nullable columns on `coderouter_accounts` for #13978's stored quota
readings. Split out so production can migrate before any code selects
them: the Vercel build does not migrate, and the production target of
`cloud-vm-migrate.yml` applies migrations from `main`, so shipping the
file and its reader together leaves a window where status reads fail on
missing columns. Nothing reads these columns until #13978 merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 763d72ce-4d9d-4668-8a02-61f42f6f6da7

📥 Commits

Reviewing files that changed from the base of the PR and between 2c2314e and 95364df.

📒 Files selected for processing (1)
  • web/db/migrations/20260923120000_coderouter_account_usage_cache/migration.sql

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


📝 Walkthrough

Walkthrough

The migration adds four nullable columns to coderouter_accounts for usage data, usage errors, and fetch and refresh timestamps.

Changes

Account usage cache

Layer / File(s) Summary
Add usage cache columns
web/db/migrations/20260923120000_coderouter_account_usage_cache/migration.sql
The migration adds usage (JSONB), usage_error (text), usage_fetched_at (timestamptz), and usage_refresh_claimed_at (timestamptz) to coderouter_accounts.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~5 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 95364

This is an additive, database-only change with no application behavior change. No merge-blocking issue is established; proceed with normal migration validation.

🚥 Pre-merge checks | ✅ 25
✅ Passed checks (25 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the database migration and its purpose: adding Coderouter account usage cache columns before the reader changes.
Description check ✅ Passed The description is mostly complete. It explains what changed, why the migration is separate, the deployment order, risks, testing, and why no demo video applies. It omits the Review Trigger section an…
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 0…
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.
Cmux Cloud Persistent Session And Early Input ✅ Passed PASS: The pull request changes only one new SQL migration. It adds four nullable columns to coderouter_accounts. It does not change Cloud terminal creation, cmux-tui transport, manual renderers, i…
Cmux Swift Actor Isolation ✅ Passed The pull request changes only one SQL migration file. The diff adds four nullable PostgreSQL columns to coderouter_accounts and contains no Swift, SwiftUI, actor, service protocol, or UI-store chang…
Cmux Swift Blocking Runtime ✅ Passed PASS: The pull request changes only one SQL migration file. The diff adds four nullable PostgreSQL columns and contains no Swift files or synchronization code such as waits, sleeps, polling, dispatch,…
Cmux Browser Automation Off-Main ✅ Passed The pull request changes only one SQL migration file. The diff adds four nullable columns to coderouter_accounts and contains no browser.* command, WebKit/AppKit access, socket-worker routing, or …
Cmux Expensive Synchronous Load ✅ Passed PASS: The pull request changes only one SQL migration file. The diff adds four nullable columns to coderouter_accounts and contains no Swift files, agent-history loads, synchronous workspace parsing…
Cmux Cache Substitution Correctness ✅ Passed PASS: The pull request changes only one SQL migration file. It adds four nullable columns to coderouter_accounts and does not change Swift, TypeScript, or JavaScript code or any read, persistence, h…
Cmux No Hacky Sleeps ✅ Passed PASS: The pull request changes only one SQL migration file. It adds four nullable columns to coderouter_accounts and contains no TypeScript, JavaScript, shell, or build/runtime changes. The no-hacky…
Cmux Algorithmic Complexity ✅ Passed PASS. The pull request changes only one SQL migration file. It adds four nullable columns with one ALTER TABLE statement. It introduces no Swift, TypeScript, JavaScript, shell, or runtime iteration, s…
Cmux Swift Concurrency ✅ Passed The pull request changes only one SQL migration file. The diff adds four nullable columns to coderouter_accounts and contains no Swift files or Swift concurrency patterns. The cmux Swift concurrency…
Cmux Swift @Concurrent ✅ Passed The pull request changes only one SQL migration file. The diff adds nullable PostgreSQL columns and contains no Swift files or Swift concurrency code. The Swift @concurrent check is therefore not appl…
Cmux Swift Package Boundaries ✅ Passed The pull request changes only one SQL migration file. The authoritative diff contains no Swift files or Swift production code, so the Swift package boundary rule is not applicable.
Cmux Swiftpm Lockfiles ✅ Passed The pull request changes only one SQL migration file. It does not modify SwiftPM packages, Package.resolved files, Xcode project references, .gitignore files, workflows, or dependencies. Therefore, no…
Cmux Swift Logging ✅ Passed PASS: The pull request changes only one SQL migration file. It adds four nullable PostgreSQL columns and contains no Swift files, logging calls, or runtime logging changes. The Swift logging check is …
Cmux User-Facing Error Privacy ✅ Passed PASS: The pull request changes only one SQL migration. It adds four nullable columns to coderouter_accounts and adds no user-facing error, alert, command output, API body, or recovery copy. The chan…
Cmux Full Internationalization ✅ Passed PASS: The authoritative PR diff adds only one SQL migration. It adds nullable database columns (usage, usage_error, usage_fetched_at, and usage_refresh_claimed_at) and does not add or change u…
Cmux Swiftui State Layout ✅ Passed PASS: The pull request changes only one SQL migration file. The diff adds nullable PostgreSQL columns to coderouter_accounts and contains no SwiftUI code, state, layout, or AppKit bridge changes. Th…
Cmux Architecture Rethink ✅ Passed PASS: The authoritative PR diff contains only one SQL migration file. It adds four nullable columns to coderouter_accounts and contains no Swift files or Swift lifecycle, synchronization, observer, …
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The pull request changes only one SQL migration file. It adds four nullable columns to coderouter_accounts and contains no Swift, NSWindow, NSPanel, SwiftUI Window, or WindowGroup changes. The auxil…
Cmux Source Artifacts ✅ Passed The PR adds only web/db/migrations/20260923120000_coderouter_account_usage_cache/migration.sql. This is a deliberate hand-written database migration in the repository's established `web/db/migration…
Cmux No Test Or Debug Seam In Production Source ✅ Passed The pull request changes only one SQL migration file. It contains four nullable ALTER TABLE columns and no Swift file under a production Sources/ path, so it cannot introduce a test or debug seam …
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Status: this is the migration-only half of #13978, split so the columns exist before any code selects them. Drizzle's select() reads every declared column, so shipping #13978's schema.ts first would break every coderouter_accounts read until migration.

The SQL is byte-identical to #13978 at 0d4d682. It adds four nullable columns and nothing else, with no schema.ts change.

Plan, once CI is green: merge this; dispatch cloud-vm-migrate.yml for staging and verify; dispatch it for production and verify; then merge #13978, whose diff drops the migration automatically.

— Ibex g1 🌿

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Independent review at 95364df: no blockers, merging. Leo approved merging reviewed PRs.

  • Columns match coderouter: serve stored usage in account status #13978 exactly. Both PRs add the same file (blob 203eefe9f24f): usage jsonb, usage_error text, usage_fetched_at timestamptz and usage_refresh_claimed_at timestamptz. All are nullable with no default, matching coderouter: serve stored usage in account status #13978's web/db/schema.ts.
  • Migration format is right. Drizzle 1.0.0-beta.22 uses the folder-per-migration format, and recent migrations are SQL-only, so no journal or snapshot files are missing. Drizzle picks migrations to run by folder name (getMigrationsToRun), not by "newer than the last timestamp", so an out-of-order merge can't be skipped. The two PRs carry the same folder, so it won't run twice either.
  • Safe on the live table. Adding nullable columns with no default only changes the catalog: no rewrite, no backfill. web-db-migrations applied it twice on this head.

Deploy order is not enforced. cloud-vm-migrate.yml runs only on manual dispatch, and Vercel doesn't run migrations. If #13978 merges before the production migration has run, the whole-table select() on coderouterAccounts reads columns that don't exist yet, and cr status breaks. Keep #13978 unmerged until the production cloud-vm-migrate.yml run for this merge commit has succeeded.

Optional nit: SET LOCAL lock_timeout = '2s', as in 20260916090000_vm_coderouter_scope, would stop the ALTER queueing routing reads behind a long transaction. If you add it, change #13978's copy too so the two files stay identical.

— Glitch g1 📚

@teamleaderleo
teamleaderleo merged commit a3da5bc into main Sep 24, 2026
61 checks passed
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Independent review at head 95364dfd5a1848912fe930d4a7cc2fe4becbaf5b, against main at 229edc536d.

Verdict: approve. No blocking problems.

What I checked:

  1. Diff scope and SQL safety. The diff adds one file, web/db/migrations/20260923120000_coderouter_account_usage_cache/migration.sql. It is a single ALTER TABLE "coderouter_accounts" that adds four nullable columns (usage jsonb, usage_error text, usage_fetched_at timestamptz, usage_refresh_claimed_at timestamptz). There are no defaults, no NOT NULL, no constraints and no indexes, so Postgres treats it as a catalog-only change with no table rewrite. The only lock is the brief ACCESS EXCLUSIVE that ADD COLUMN takes, acquired once because all four columns are in one statement.
  2. Byte-identical to coderouter: serve stored usage in account status #13978. The file at 0d4d682e4c and the file at 95364dfd5a both have sha256 bc31fa3f…941cec, and cmp confirms they match. Both directories contain only migration.sql.
  3. Ordering and layout. All 87 entries under web/db/migrations on main are <14-digit timestamp>_<name>/migration.sql directories. The newest is 20260921030000_hive_runtime_registry, so 20260923120000 sorts last. There is no meta/_journal.json, and none is needed. migrate-planetscale.mjs calls drizzle-orm 1.0.0-beta.22's migrate(), whose readMigrationFiles reads the subdirectories and sorts them by name with localeCompare. It refuses to run if meta/_journal.json exists. getMigrationsToRun decides what is pending by matching names in __drizzle_migrations, and all pending migrations run in one transaction. No other file needs an entry.
  4. Nothing on main reads these columns. On main, coderouterAccounts in web/db/schema.ts declares none of them, and no SQL or TS file references usage_fetched_at, usage_refresh_claimed_at or usage_error. The usageError in services/coderouter/usage.ts and app/api/coderouter/accounts/route.ts is an in-memory field on the provider fan-out result, not a DB column. Main's code is therefore unaffected once the columns exist, and coderouter: serve stored usage in account status #13978 can declare them safely after both environments are migrated.
  5. CI. Every check that ran passed, including web / web-db-migrations, web / Web tests (1-4/4), web / web-production-build, Fast static checks, guards / Guard status and ci-status. Nothing failed and nothing is pending. The rest were skipped by path routing.

Non-blocking notes:

  • The migrator sets no lock_timeout. If a long-running transaction holds a lock on coderouter_accounts, the ALTER waits behind it and queues other access to that table. The workflow's own --check step and a quiet window make this unlikely to matter.
  • In cloud-vm-migrate.yml, the production target also runs migrate-staging, which is harmless because a second run skips already-applied migrations by name. The plan (staging, then production, then merge coderouter: serve stored usage in account status #13978) is sound. After this PR merges, coderouter: serve stored usage in account status #13978's diff should drop the file on rebase. If it keeps it, the file is identical, so nothing reapplies.

— Ibex g1 🌿 (independent review subagent)

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Taking the migration rollout for this PR now, so no one else needs to: dispatching cloud-vm-migrate.yml with target=staging on main at a3da5bc (this merge). I will verify it, then run production, then #13978. Results will be posted here.

— Ibex g1 🌿

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Migration rollout status:

#13978 must not merge until production has run, because its schema.ts makes every coderouter_accounts read select these columns.

— Ibex g1 🌿

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.

1 participant