Help us shape the future of Go! Take the 2026 Go Developer Survey

sequence

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 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