jevstrudel.git / worker / src / budget.ts

The per-user daily Jev budget: one JevBudget Durable Object per signed-in user (BUDGET.idFromName(userId)), counting that user's relay calls per UTC day in its own SQLite storage. The counting is budget-counter.ts; the limit is wrangler.json's JEV_DAILY_PER_USER, read here from the object's own env so there is one source for it.

A Durable Object, not D1: the count is live coordination (every tab and device of one user racing to spend the same allowance), and an object runs one call at a time, so the check and the charge cannot interleave. It is not a record: yesterday's count is deleted as today's begins.

11import { DurableObject } from 'cloudflare:workers';
12import { balance, createSchema, dailyLimit, spend, type Balance, type Spend } from './budget-counter';
14type BudgetEnv = { JEV_DAILY_PER_USER?: unknown };
15
16export class JevBudget extends DurableObject<BudgetEnv> {
17  constructor(ctx: DurableObjectState, env: BudgetEnv) {
18    super(ctx, env);
19    createSchema(ctx.storage.sql);
20  }

Charges calls relay calls (one, unless said) to today, unless they do not all fit in what is left of today's budget.

24  spend(calls = 1): Spend {
25    return spend(this.ctx.storage.sql, dailyLimit(this.env.JEV_DAILY_PER_USER), Date.now(), calls);
26  }

Today's count, without charging.

29  balance(): Balance {
30    return balance(this.ctx.storage.sql, dailyLimit(this.env.JEV_DAILY_PER_USER), Date.now());
31  }
32}