improvement(billing): share the enterprise reporting usage read across processes

Merged
WA
1mo ago
+759-198

Summary

  • Enterprise reporting-window usage sums (a year-long ledger scan) are now shared across processes through Redis with a 30s TTL. Trigger.dev runs every task in a fresh process, so the existing in-process LRU was always cold there, and the scan ran on nearly every document-processing and execution admission check
  • The in-process LRU stays in front and still coalesces concurrent misses. The Redis GET has a 250ms deadline, and any Redis error, timeout, or unreadable value falls through to the exact sum. The write is a fire-and-forget SET … NX with a jittered TTL, so a slower, older sum never overwrites a fresher one or extends its life. There is no lock or lease
  • The usage threshold email is now level-triggered, instead of being edge-triggered off an exact before/after org sum on every workflow completion. A claim keyed on (billing period, limit) (claimCreditsThreshold) sends each threshold at most once. A new period or a changed limit re-arms it with no reset write, and concurrent completions can't both send
  • Recipients are resolved before claiming, so a period's email isn't used up when nobody can receive it. Zero-cost completions don't claim. The personal usage baseline and the claimed period come from the same billing context
  • Invoicing, cycle close, overage, and threshold billing still read the ledger exactly
  • Rollout note: accounts already at or above 80% this billing period get one threshold email after deploy; there is no backfill

Type of Change

  • Improvement

Testing

  • New integration tests against real Postgres and Redis (reporting-usage-cache.integration.ts, usage-threshold-email.integration.ts). Six of the seven fail on the pre-change code. The Redis-unreachable test goes red if the read deadline is removed
  • Covered: a Redis hit skips the sum; a miss sums and stores it with a TTL; a corrupt value is treated as a miss; one email per period across concurrent and repeated completions; 80% then 100%, never the reverse; re-arm next period
  • lib/billing and lib/logs/execution unit suites, type-check, lint, and check:audits pass

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)