mirror of
https://github.com/simstudioai/sim.git
synced 2026-10-29 18:47:25 +08:00
* improvement(billing): paginate and parallelize the cycle-close sweep The sweep previously loaded every lagging candidate in one select and closed them serially — correct at any scale (per-subscription guarded marker claims make any interleaving safe) but O(fleet) in memory and wall clock. It now iterates candidates in keyset pages and closes each page with bounded concurrency; a total mapper keeps one failure from rejecting its page, and an interrupted sweep resumes from the durable markers on the next run. The member-lock select gains a deterministic ORDER BY: today member_user_id_unique keeps org rosters disjoint and every other locker is single-row, so no deadlock is currently constructible — the ordering is hygiene that also holds if membership exclusivity is ever relaxed. A partial index on exactly the sweep's candidate predicate (built CONCURRENTLY behind the runner's COMMIT breakpoint) keeps the scan O(lagging) rather than O(fleet); closes shrink it as they land. Validated end-to-end against Stripe test mode: one sweep over 304 staged lagging subscriptions (300 synthetic + 2 multi-member orgs closing concurrently + 2 real test-clock subscriptions with genuine overage) closed 304/304 with failed=0 in 667ms — the same fleet took ~302s serially — while both real subscriptions produced exactly one paid overage invoice each at the expected amounts, with zero invoices for the no-overage fleet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(billing): restore the runner's lock_timeout and inline entitled statuses for the sweep index The concurrent-index migration now restores lock_timeout='5s' after its post-COMMIT section, matching the runner convention every prior CONCURRENTLY migration follows — without it, later pending files' DDL in the same session would wait indefinitely instead of hitting the runner's 55P03 retry path. The sweep's status filter becomes inlined literals derived from ENTITLED_SUBSCRIPTION_STATUSES: the planner can only prove a query implies a partial index's predicate from literals, and the parameterized generic plan demonstrably seq-scans where the literal form uses subscription_cycle_close_lagging_idx. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>