Documentation
¶
Overview ¶
Package outbox provides transactional outbox records and relay primitives.
Persisting an Envelope atomically with application state requires passing the same caller-owned database transaction to a transactional store. Publishing is at least once: consumers must tolerate duplicate envelopes.
Example (DuplicateDeliveryRequiresIdempotentConsumer) ¶
package main
import (
"fmt"
"github.com/faustbrian/go-outbox"
)
func main() {
consumer := idempotentConsumer{seen: make(map[string]struct{})}
envelope := outbox.Envelope{ID: "evt-42", Topic: "orders.created"}
consumer.Consume(envelope)
consumer.Consume(envelope) // relay redelivery after an ambiguous result
fmt.Println(consumer.effects)
}
type idempotentConsumer struct {
seen map[string]struct{}
effects int
}
func (consumer *idempotentConsumer) Consume(envelope outbox.Envelope) {
if _, duplicate := consumer.seen[envelope.ID]; duplicate {
return
}
consumer.seen[envelope.ID] = struct{}{}
consumer.effects++
}
Output: 1
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrIDRequired = errors.New("outbox: ID is required") ErrIDTooLarge = errors.New("outbox: ID is too large") ErrTopicRequired = errors.New("outbox: topic is required") ErrTopicTooLarge = errors.New("outbox: topic is too large") ErrPayloadTooLarge = errors.New("outbox: payload is too large") ErrMetadataTooLarge = errors.New("outbox: metadata is too large") ErrMetadataEntriesTooLarge = errors.New("outbox: metadata has too many entries") ErrOrderingKeyTooLarge = errors.New("outbox: ordering key is too large") ErrIdempotencyKeyTooLarge = errors.New("outbox: idempotency key is too large") ErrPayloadVersionRequired = errors.New("outbox: payload version is required") ErrAttemptsInvalid = errors.New("outbox: new envelope attempts must be zero") ErrAvailableAtRequired = errors.New("outbox: availability time is required") ErrCreatedAtRequired = errors.New("outbox: creation time is required") ErrTimestampOutOfRange = errors.New("outbox: timestamp is outside JSON range") ErrInvalidLimits = errors.New("outbox: limits must be positive") )
Functions ¶
This section is empty.
Types ¶
type BacklogStats ¶
BacklogStats summarizes operationally relevant message states.
type Envelope ¶
type Envelope struct {
ID string `json:"id"`
Topic string `json:"topic"`
Payload []byte `json:"payload"`
PayloadVersion uint16 `json:"payload_version"`
Metadata map[string]string `json:"metadata,omitempty"`
OrderingKey string `json:"ordering_key,omitempty"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
Attempts int `json:"attempts"`
AvailableAt time.Time `json:"available_at"`
CreatedAt time.Time `json:"created_at"`
}
Envelope is the stable record transferred from PostgreSQL to a publisher. Attempts is zero when written and increases when a claim is published.
func (Envelope) CanonicalJSON ¶
CanonicalJSON returns a deterministic JSON representation. The wire struct has a fixed field order, metadata keys are sorted by encoding/json, and timestamps are formatted explicitly so encoding cannot fail on a time year.
func (Envelope) ValidateForInsert ¶
ValidateForInsert checks a new envelope against limits and persistence invariants. Writers call this again because callers can construct the exported Envelope type without using EnvelopeBuilder.
type EnvelopeBuilder ¶
type EnvelopeBuilder struct {
// contains filtered or unexported fields
}
EnvelopeBuilder validates and constructs new envelopes.
func NewEnvelopeBuilder ¶
func NewEnvelopeBuilder(options ...EnvelopeBuilderOption) (*EnvelopeBuilder, error)
NewEnvelopeBuilder creates a bounded envelope builder.
func (*EnvelopeBuilder) Build ¶
func (b *EnvelopeBuilder) Build(params NewEnvelopeParams) (Envelope, error)
Build creates a validated envelope and takes ownership by copying mutable payload and metadata values.
type EnvelopeBuilderOption ¶
type EnvelopeBuilderOption func(*EnvelopeBuilder) error
EnvelopeBuilderOption configures an EnvelopeBuilder.
func WithClock ¶
func WithClock(clock func() time.Time) EnvelopeBuilderOption
WithClock injects the clock used for creation and default availability.
func WithIDGenerator ¶
func WithIDGenerator(generator func() (string, error)) EnvelopeBuilderOption
WithIDGenerator injects the envelope ID generator.
func WithLimits ¶
func WithLimits(limits Limits) EnvelopeBuilderOption
WithLimits replaces all envelope size limits.
type Event ¶
type Event struct {
Operation Operation
Outcome Outcome
Count int
MessageID string
Topic string
Attempts int
Duration time.Duration
}
Event contains payload-safe diagnostics for one outbox operation. It never includes payloads, metadata, or error text.
type Limits ¶
type Limits struct {
MaxIDBytes int
MaxTopicBytes int
MaxPayloadBytes int
MaxMetadataEntries int
MaxMetadataBytes int
MaxOrderingKeyBytes int
MaxIdempotencyKeyBytes int
}
Limits bounds all caller-controlled variable-length envelope fields.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns conservative defaults suitable for most relays.
type NewEnvelopeParams ¶
type NewEnvelopeParams struct {
Topic string
Payload []byte
PayloadVersion uint16
Metadata map[string]string
OrderingKey string
IdempotencyKey string
AvailableAt time.Time
}
NewEnvelopeParams contains caller-controlled data for a new envelope.
type ObserverFunc ¶
ObserverFunc adapts a function to Observer.
type Operation ¶
type Operation string
Operation identifies a bounded outbox lifecycle action.
const ( OperationClaim Operation = "claim" OperationPublish Operation = "publish" OperationDeliver Operation = "deliver" OperationRetry Operation = "retry" OperationDeadLetter Operation = "dead_letter" OperationRelease Operation = "release" OperationExtendLease Operation = "extend_lease" OperationReplay Operation = "replay" OperationPrune Operation = "prune" OperationArchive Operation = "archive" )
Directories
¶
| Path | Synopsis |
|---|---|
|
adapters
|
|
|
goqueue
module
|
|
|
gotelemetry
module
|
|
|
Package postgres provides pgx-backed transactional persistence for outbox envelopes.
|
Package postgres provides pgx-backed transactional persistence for outbox envelopes. |
|
Package relay publishes claimed outbox envelopes with bounded concurrency.
|
Package relay publishes claimed outbox envelopes with bounded concurrency. |