Documentation
¶
Overview ¶
Package inventory is a generic owned-item ledger: "subject owns N of item type X" with atomic transfers, idempotent mutations, and reservation holds.
The semantics are domain-agnostic:
- Player inventories and currency (games).
- Portfolio positions, lot-tracked holdings (trading).
- Shop stock and cart contents (e-commerce).
- Warehouse asset registers (logistics).
Every mutation is identified by an idempotency key so retries are safe. Holds reserve quantity for a TTL; they can be committed (turn into a consume) or released (return to free balance). This package ships an in-memory Ledger; Postgres- and event-sourced backends are pluggable behind the Ledger interface.
Index ¶
- Variables
- type Balance
- type HoldID
- type Idempotency
- type ItemTypeID
- type Ledger
- type MemoryConfig
- type MemoryLedger
- func (l *MemoryLedger) Acquire(_ context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64) error
- func (l *MemoryLedger) Balance(_ context.Context, subj SubjectID, item ItemTypeID) (Balance, error)
- func (l *MemoryLedger) Commit(_ context.Context, hold HoldID) error
- func (l *MemoryLedger) Consume(_ context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64) error
- func (l *MemoryLedger) Hold(_ context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64, ...) (HoldID, error)
- func (l *MemoryLedger) List(_ context.Context, subj SubjectID) ([]Balance, error)
- func (l *MemoryLedger) Release(_ context.Context, hold HoldID) error
- func (l *MemoryLedger) Transfer(_ context.Context, key Idempotency, from, to SubjectID, item ItemTypeID, ...) error
- type SubjectID
Constants ¶
This section is empty.
Variables ¶
var ( ErrInsufficient = errors.New("inventory: insufficient quantity") ErrInvalidQuantity = errors.New("inventory: quantity must be > 0") ErrHoldUnknown = errors.New("inventory: hold not found") ErrHoldExpired = errors.New("inventory: hold expired") )
Errors surfaced by Ledger implementations.
Functions ¶
This section is empty.
Types ¶
type Balance ¶
type Balance struct {
Subject SubjectID
Item ItemTypeID
Quantity int64
OnHold int64
}
Balance is the projected free + held quantity for a (subject, item) pair.
type Idempotency ¶
type Idempotency string
Idempotency is a client-supplied key that makes a mutation safe to retry. Two calls with the same key must have the effect of one.
type ItemTypeID ¶
type ItemTypeID string
ItemTypeID identifies the kind of thing being held (sku, currency, item-id, asset symbol).
type Ledger ¶
type Ledger interface {
// Acquire credits qty of item to subject. Idempotent on key.
Acquire(ctx context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64) error
// Consume debits qty. Returns ErrInsufficient if free quantity is
// less than qty. Idempotent on key.
Consume(ctx context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64) error
// Transfer moves qty from one subject to another atomically.
// Idempotent on key.
Transfer(ctx context.Context, key Idempotency, from, to SubjectID, item ItemTypeID, qty int64) error
// Hold reserves qty for ttl. Held quantity is debited from free
// (Quantity) and added to OnHold until Commit or Release.
Hold(ctx context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64, ttl time.Duration) (HoldID, error)
// Commit turns a hold into a consume.
Commit(ctx context.Context, hold HoldID) error
// Release returns held quantity to free balance.
Release(ctx context.Context, hold HoldID) error
// Balance returns the current balance for a (subject, item) pair.
Balance(ctx context.Context, subj SubjectID, item ItemTypeID) (Balance, error)
// List returns all non-zero balances for a subject.
List(ctx context.Context, subj SubjectID) ([]Balance, error)
}
Ledger is the public interface for an inventory ledger. Implementations must be safe for concurrent use.
type MemoryConfig ¶
type MemoryConfig struct {
// Clock supplies the current time; defaults to time.Now if nil.
Clock func() time.Time
}
MemoryConfig configures a MemoryLedger.
type MemoryLedger ¶
type MemoryLedger struct {
// contains filtered or unexported fields
}
MemoryLedger is an in-process Ledger. Goroutine-safe; mutations are serialised behind a single mutex which is plenty for tests and single-binary use cases.
func NewMemoryLedger ¶
func NewMemoryLedger(cfg MemoryConfig) *MemoryLedger
NewMemoryLedger constructs a MemoryLedger.
func (*MemoryLedger) Acquire ¶
func (l *MemoryLedger) Acquire(_ context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64) error
Acquire implements Ledger.
func (*MemoryLedger) Balance ¶
func (l *MemoryLedger) Balance(_ context.Context, subj SubjectID, item ItemTypeID) (Balance, error)
Balance implements Ledger.
func (*MemoryLedger) Commit ¶
func (l *MemoryLedger) Commit(_ context.Context, hold HoldID) error
Commit implements Ledger.
func (*MemoryLedger) Consume ¶
func (l *MemoryLedger) Consume(_ context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64) error
Consume implements Ledger.
func (*MemoryLedger) Hold ¶
func (l *MemoryLedger) Hold(_ context.Context, key Idempotency, subj SubjectID, item ItemTypeID, qty int64, ttl time.Duration) (HoldID, error)
Hold implements Ledger.
func (*MemoryLedger) Release ¶
func (l *MemoryLedger) Release(_ context.Context, hold HoldID) error
Release implements Ledger.
func (*MemoryLedger) Transfer ¶
func (l *MemoryLedger) Transfer(_ context.Context, key Idempotency, from, to SubjectID, item ItemTypeID, qty int64) error
Transfer implements Ledger.