Documentation
¶
Overview ¶
Package sequence provides a gap-free, race-free per-tenant numbered-series allocator for statutory documents (receipts, vouchers, certificates) — the primitive that keeps products off MAX()+1 (roadmap E3).
Allocate runs INSIDE the caller's tenant transaction: the counter increment commits or rolls back atomically with the business write, so a number is consumed only on commit (gap-free) and concurrent allocations serialize on the counter row (race-free). This is deliberately NOT a Postgres sequence — nextval() does not roll back and therefore leaves gaps, which is unacceptable for statutory numbering. The cost is that allocations on one series serialize; that is inherent to gap-free numbering.
Index ¶
- type Allocation
- type Allocator
- func (a *Allocator) Allocate(ctx context.Context, db database.TenantDB, seriesKey string) (Allocation, error)
- func (a *Allocator) Peek(ctx context.Context, db database.TenantDB, seriesKey string) (int64, error)
- func (a *Allocator) Void(ctx context.Context, db database.TenantDB, seriesKey string, value int64, ...) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Allocation ¶
Allocation is a single issued number and its ledger identity.
type Allocator ¶
type Allocator struct {
// contains filtered or unexported fields
}
Allocator issues and voids numbers in per-tenant series. It is stateless; all state lives in the sequences / sequence_allocations tables under RLS.
func (*Allocator) Allocate ¶
func (a *Allocator) Allocate(ctx context.Context, db database.TenantDB, seriesKey string) (Allocation, error)
Allocate consumes the next value in seriesKey for the current tenant and writes a ledger row, all within db's transaction. Because the increment lives in the caller's tx, a rollback frees the number (gap-free) and parallel callers block on the counter row rather than colliding (race-free). seriesKey must be non-empty.
func (*Allocator) Peek ¶
func (a *Allocator) Peek(ctx context.Context, db database.TenantDB, seriesKey string) (int64, error)
Peek returns the last value issued in a series without consuming one (0 if the series has never allocated). Read path — safe in a read-only tx.
func (*Allocator) Void ¶
func (a *Allocator) Void(ctx context.Context, db database.TenantDB, seriesKey string, value int64, reason string) error
Void marks an issued number voided with a reason, for audit. The number is NOT reissued — the gap is intentional and traceable (a voided statutory document leaves a hole, it is never silently renumbered). Returns KindNotFound if the value was never allocated in this series, KindConflict if already voided.