Documentation
¶
Overview ¶
Package postgres provides durable atomic capability consumption through database/sql and PostgreSQL row locks. Start with the explicit schema/legacy ownership migration and NewConsumptionStore; the caller supplies/owns the SQL driver, database, credentials and timeouts. Store calls own their replay transactions, not a protected business transaction, worker or database close. Read-committed row locking and a finite insert-race retry preserve DEC-008; unknown commit outcomes require application reconciliation, not blind retries.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MigrateLegacyConsumption ¶
MigrateLegacyConsumption upgrades migration 001 to the issuer-scoped schema version 2, preserving every use count, maximum and expiry. legacyIssuer must be the owner-proven single issuer of all existing rows, never a token claim. The caller must fence and drain all old writers first and supply an open transaction. This function locks the table but does not commit or roll back; on failure the caller must roll back. Commit before activating new writers. Repeating this on an upgraded schema fails rather than acting as a no-op. Direct SQL errors remain caller-owned diagnostics. Unknown legacy ownership requires retiring old grants beyond expiry plus verification skew instead.
Types ¶
type ConsumptionStore ¶
type ConsumptionStore struct {
// contains filtered or unexported fields
}
ConsumptionStore owns per-call replay transactions, not database lifetime. Construct with NewConsumptionStore; zero is unusable. Concurrent use follows database/sql and row locks, not a process mutex. No business effect is joined.
func NewConsumptionStore ¶
func NewConsumptionStore(db *sql.DB) (*ConsumptionStore, error)
NewConsumptionStore binds store to db. The schema in migrations must be installed and MigrateLegacyConsumption committed before use. db remains caller-owned and is never closed here.
func (*ConsumptionStore) Cleanup ¶
Cleanup deletes state at/before nonzero cutoff in one owned transaction. Call with non-nil ctx; caller chooses a safe cutoff beyond relevant acceptance windows and supplies operational deadlines. Returned count is committed only on nil error; commit failure returns zero with an unknown deletion outcome.
func (*ConsumptionStore) Consume ¶
func (store *ConsumptionStore) Consume(ctx context.Context, request capability.Consumption) (capability.ConsumptionResult, error)
Consume serializes one capability row, then commits an increment only when the signed issuer/ID, live expiry and maximum match. ctx must be non-nil; issuer/ID are nonempty UTF-8 <=256 bytes. Expiry truncates to microseconds and is checked against transaction time, not verifier skew or a post-lock clock. Insert races retry at most three transactions; depletion/conflict commit no use. Other driver/commit errors remain raw and may have unknown outcome. Grant.Consume adds the safe normalization boundary; direct calls do not.