outbox

package
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package outbox is the transactional-outbox relay: it leases due rows from an interfaces.OutboxStore, delivers them through an interfaces.OutboxSink in bounded-concurrency chunks, and finalizes each row by its own outcome — sent, retried with capped exponential backoff and full jitter, or parked once its attempts are exhausted. It reports per-lane outcome counters and the lane's depth and lag. The store and sink are injected (and decorated) by the caller.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Option

type Option func(*Relay)

Option customizes a Relay beyond its config (the deterministic seams tests use).

func WithClock

func WithClock(now func() time.Time) Option

WithClock sets the clock retry times are computed from (default time.Now).

func WithJitter

func WithJitter(jitter func(time.Duration) time.Duration) Option

WithJitter sets how the capped backoff is randomized (default retry.FullJitter, a uniform draw from [0, cap]).

type Relay

type Relay struct {
	// contains filtered or unexported fields
}

Relay moves outbox rows from a store to a sink. It is safe for concurrent RunOnce calls (the store's claim keeps them disjoint).

func NewRelay

func NewRelay(
	cfg RelayConfig,
	store interfaces.OutboxStore,
	sink interfaces.OutboxSink,
	logger interfaces.Logger,
	metrics interfaces.Metrics,
	tracer interfaces.Tracer,
	opts ...Option,
) *Relay

NewRelay builds a relay over store and sink. logger, metrics and tracer may be nil. An invalid cfg or a nil store or sink is a wiring bug and panics; build cfg with LoadRelayConfig (or call cfg.Validate first) to get a coded error instead.

func (*Relay) RunOnce

func (r *Relay) RunOnce(ctx context.Context) error

RunOnce claims one batch, delivers it and finalizes every row, then refreshes the lane gauges. The claim is called exactly once (it is side-effecting, so it is never retried here). A finalize failure does not stop the other rows — the row's lease expires and it is re-claimed — and the first such error is returned. A Stats failure is only logged; with metrics off Stats is skipped.

type RelayConfig

type RelayConfig struct {
	// Lane is the outbox lane drained.
	Lane string `yaml:"lane" mapstructure:"lane"`
	// BatchSize is the most rows one RunOnce claims.
	BatchSize int `yaml:"batch_size" mapstructure:"batch_size"`
	// SendBatch is the most records handed to one Sink.Send call.
	SendBatch int `yaml:"send_batch" mapstructure:"send_batch"`
	// Concurrency bounds how many Send calls run at once.
	Concurrency int `yaml:"concurrency" mapstructure:"concurrency"`
	// MaxAttempts is the attempt on which a still-failing record is parked.
	MaxAttempts int `yaml:"max_attempts" mapstructure:"max_attempts"`
	// BaseBackoff is the backoff unit: a record that failed attempt n waits up to
	// BaseBackoff·2^n before its next attempt.
	BaseBackoff time.Duration `yaml:"base_backoff" mapstructure:"base_backoff"`
	// MaxBackoff caps the backoff before jitter.
	MaxBackoff time.Duration `yaml:"max_backoff" mapstructure:"max_backoff"`
	// ParkOnPermanent parks a record on its first permanent failure (one
	// coreerr.IsPermanent reports, e.g. a malformed payload the destination
	// rejects) instead of retrying it until MaxAttempts.
	ParkOnPermanent bool `yaml:"park_on_permanent" mapstructure:"park_on_permanent"`
}

RelayConfig tunes one relay; one relay drains one lane.

func DefaultRelayConfig

func DefaultRelayConfig(lane string) RelayConfig

DefaultRelayConfig returns a relay config for lane: claim 100 rows, send 10 at a time with 4 concurrent sends, park on the 10th attempt, back off from 1s up to 5m.

func LoadRelayConfig

func LoadRelayConfig(loader interfaces.ConfigLoader, key, lane string) (RelayConfig, error)

LoadRelayConfig reads the relay config for lane from loader's key section, overlaid on DefaultRelayConfig(lane), and validates it. An absent section yields the defaults; an unreadable or invalid one is CodeInvalidInput. Load through it so a bad section stops boot with a coded error, never NewRelay's panic.

func (RelayConfig) Validate

func (c RelayConfig) Validate() error

Validate reports a config the relay cannot run with as CodeInvalidInput.

Jump to

Keyboard shortcuts

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