The subscription reconcile changes provision status without the pool lock #193

Open
opened 2026-10-07 08:00:28 +00:00 by cgalo5758 · 0 comments
Owner

When a Stripe subscription becomes past due, unpaid or paused, ReconcileSubscription (internal/fulfillment/reconcile.go) marks its provisions suspended through SyncSourceStatus and materializes the pool without taking the pool row lock. When the subscription is active again, the same function resumes those provisions through SyncSourceStatus before any call that takes the lock. Every other path that changes a pool's positions or entitlements locks the pool row first, and the five conferral functions take it themselves (docs/database-locks.md).

The reconcile holds only the shared materialization lock and the subscription's own lock, so an operator act on the same pool, such as issuing or revoking a grant, can run at the same time. Each transaction then computes the pool's entitlements without the other's uncommitted change, and whichever commits last writes its result. The pool keeps entitlements that miss one of the two changes until something materializes it again.

Done when: the reconcile takes the pool row lock before it changes a provision's status, in both branches; a test runs a status change and a grant act on one pool at the same time and checks the stored entitlements against the provisions; and the entry for the suspended branch under "Where the paths differ" in docs/database-locks.md is gone.

When a Stripe subscription becomes past due, unpaid or paused, `ReconcileSubscription` (`internal/fulfillment/reconcile.go`) marks its provisions suspended through `SyncSourceStatus` and materializes the pool without taking the pool row lock. When the subscription is active again, the same function resumes those provisions through `SyncSourceStatus` before any call that takes the lock. Every other path that changes a pool's positions or entitlements locks the pool row first, and the five conferral functions take it themselves (`docs/database-locks.md`). The reconcile holds only the shared materialization lock and the subscription's own lock, so an operator act on the same pool, such as issuing or revoking a grant, can run at the same time. Each transaction then computes the pool's entitlements without the other's uncommitted change, and whichever commits last writes its result. The pool keeps entitlements that miss one of the two changes until something materializes it again. Done when: the reconcile takes the pool row lock before it changes a provision's status, in both branches; a test runs a status change and a grant act on one pool at the same time and checks the stored entitlements against the provisions; and the entry for the suspended branch under "Where the paths differ" in `docs/database-locks.md` is gone.
cgalo5758 added the
kind
bug
area/entitlementsarea/billing
labels 2026-10-07 08:00:29 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wiki-cafe/member-console#193