Skip to content

perf(worker): cache bot list and model pricing reads - #112

Merged
tpaulshippy merged 2 commits into
mainfrom
perf/cache-bots-pricing
Nov 2, 2026
Merged

tpaulshippy merged 2 commits into
mainfrom
perf/cache-bots-pricing

Conversation

@tpaulshippy

@tpaulshippy tpaulshippy commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Cuts the hottest D1 readers to near zero.

Bot list (GET /api/bots/, worker/src/routes/bots.ts)

  • Per-user infinite in-memory cache (single isolate), write-through invalidation on POST/PUT/PATCH/DELETE, OAuth default-bot provisioning, and onboarding bootstrap
  • Per-bot SELECT model_id FROM bots_aimodel N+1 replaced with one batched WHERE id IN (...)

Model pricing (worker/src/usage.ts)

  • bots_aimodel is runtime-static (no worker route writes it), so rows load once per isolate and are shared by rawCostForToday + baselinePricingSnapshot (previously 2 full scans per quota check, on every chat turn)

Tests (worker/tests/api.test.ts)

  • Reset both caches in beforeEach — fresh DB per case would otherwise leak rows through module state

Verified

  • tsc --noEmit clean, vitest 51/51 pass (local seeded DB; no prod reads)

Staleness notes

  • Bot list: entries live until invalidated. Direct D1 console edits won't show until redeploy; any future bots_bot writer must call invalidateBotListCache.
  • Pricing: any future runtime writer must call `invalidateModelsCache()$.

Summary by cubic

Reduces the hottest D1 reads to near zero by caching the per-user bot list and the bots_aimodel pricing table in worker memory. The bot list's per-bot N+1 lookup becomes a single batched query, and pricing rows load once per isolate instead of twice per quota check on every chat turn.

Cache notes

  • Bot list entries live until invalidated; POST/PUT/PATCH/DELETE, OAuth provisioning, and onboarding bootstrap trigger invalidation, but direct D1 console edits won't appear until redeploy. An epoch guard drops rows a GET started reading before a mid-read bot write.
  • Pricing rows are safe to cache because no worker route writes bots_aimodel; any future runtime writer must call invalidateModelsCache(). An empty table is never cached, so costs can't pin at zero and silently stop enforcing the daily cap.
  • Tests reset both caches in beforeEach; a new cache.test.ts covers the epoch guard, eviction cap, and empty-pricing behavior.

Written for commit 44489b9. Summary will update on new commits.

View guided diff Turn on auto-fix

- GET /api/bots/: per-user infinite in-memory list cache with
  write-through invalidation on POST/PUT/PATCH/DELETE, OAuth
  provisioning, and onboarding bootstrap; single batched aimodel
  lookup replaces N per-bot queries
- usage.ts: bots_aimodel pricing loaded once per isolate (runtime-
  static table); shared by rawCostForToday and baselinePricingSnapshot
- tests: reset both caches in beforeEach (fresh DB per case)

Verified: tsc --noEmit clean, vitest 51/51 pass.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread worker/src/routes/bots.ts Resolved
Comment thread worker/src/usage.ts Resolved
Comment thread worker/src/routes/bots.ts Resolved
Comment thread worker/src/onboarding.ts Resolved
- botListCache: per-isolate epoch; in-flight GETs whose reads started
  before a bot write no longer store pre-write rows (P2)
- usage: never cache an empty bots_aimodel result, or costs pin at 0
  and the daily cap stops enforcing (P2)
- extract bot-list cache to worker/src/botListCache.ts so onboarding
  and oauth no longer import the route module (P3)
- tests/cache.test.ts: epoch-guard, eviction, and empty-pricing
  regression tests (55/55 pass)
@tpaulshippy

Copy link
Copy Markdown
Owner Author

@cubic-dev-ai incremental review

@cubic-dev-ai

cubic-dev-ai Bot commented Nov 2, 2026

Copy link
Copy Markdown

@cubic-dev-ai incremental review

@tpaulshippy I’ve started reviewing the changes since the last completed review. I’ll post the results here when it’s done.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 7 files (changes from recent commits).

View guided diff | Turn on auto-fix | Re-trigger cubic

@tpaulshippy
tpaulshippy merged commit 28b8074 into main Nov 2, 2026
5 checks passed
@tpaulshippy
tpaulshippy deleted the perf/cache-bots-pricing branch November 2, 2026 01:06
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