sequence

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Allocation

type Allocation struct {
	ID    uuid.UUID
	Value int64
}

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 New

func New(idgen model.IDGen) *Allocator

New builds an Allocator. idgen mints ledger row ids (UUIDv7).

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL