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

deadletter

package
v0.18.0 Latest Latest
Warning

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

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

Documentation

Overview

Package deadletter is the eventing dead-letter queue PORT (ADR-0118, F85): the durable park for a Sensor action-delivery that failed past the bounded retry cap, or that was parked before its attempts ran out (ADR-0156: the Sensor's queue was full, the Sensor changed, or the daemon shut down). It is deliberately BUS-DRIVER-INDEPENDENT — the same store serves the in-memory and NATS buses, so the reliability guarantee never hinges on a JetStream feature (this package imports NO bus). Records are engine-minted, high-volume operational data (like the ADR-0094 run store), NOT a CRD: they live in a dedicated Badger instance surfaced by a read + replay/discard control-plane surface, never the metastore.

The port has two V1 drivers, each in its own subpackage, both held to the shared Contract: badger (in-memory mode for tests/dev, on-disk for production) and memory (a small pure-map driver for cross-platform tests). See deadletter/badger and deadletter/memory.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Contract

func Contract(t *testing.T, newStore func(t *testing.T) Store)

Contract exercises the deadletter.Store port against a driver. Every driver's test runs it (ADR-0002 shared contract suite), so badger and memory are held to one behavior: roundtrip, not-found, list newest-first + namespace scope, update (existing only), delete (idempotent), no-aliasing, and the retention sweep (TTL + per-ns cap). It is the `retention-evicts`, `discard-removes` and `driver-independent` store-level evidence.

Types

type DeadLetter

type DeadLetter struct {
	ID        string           `json:"id"`        // ULID — time-sortable within a namespace (cheap cap eviction)
	Namespace v1.NamespaceName `json:"namespace"` //
	Sensor    v1.ObjectName    `json:"sensor"`    // the Sensor whose action failed
	Source    v1.ObjectName    `json:"source"`    // the EventSource — from the delivery unit's dependency tuple
	Event     v1.ObjectName    `json:"event"`     // the event name — from the delivery unit's dependency tuple
	Action    string           `json:"action"`    // the Sensor action name (do[].name)
	Payload   json.RawMessage  `json:"payload"`   // the full CloudEvent JSON (re-injected verbatim on replay)
	Attempts  int              `json:"attempts"`  // delivery attempts made before dead-lettering (0 if never attempted)
	Reason    string           `json:"reason"`    // the terminal delivery error, or the park reason (ADR-0156)
	FailedAt  v1.Timestamp     `json:"failedAt"`  //
}

DeadLetter is a terminally-undeliverable Sensor action, or one parked before its attempts ran out (ADR-0156), kept for inspection/replay. It carries the full firing CloudEvent (Payload) so replay can re-inject it verbatim, plus the provenance to re-find the action on the LIVE Sensor spec. It is built from the Sensor's in-memory delivery unit (the dependency's source/event tuple), never by re-parsing the CloudEvent.

func Clone

func Clone(dl DeadLetter) (DeadLetter, error)

Clone deep-copies a record so drivers never alias caller-owned memory.

type Store

type Store interface {
	// Put creates or replaces a dead-letter record.
	Put(ctx context.Context, dl DeadLetter) error
	// Update replaces an existing record, or returns fault.NotFound if it is absent: replay re-parks with it,
	// so a discard or a retention sweep made during the replay stays in effect.
	Update(ctx context.Context, dl DeadLetter) error
	// List returns a namespace's dead letters, newest first (ID descending).
	List(ctx context.Context, ns v1.NamespaceName) ([]DeadLetter, error)
	// Get returns one record, or fault.NotFound if absent.
	Get(ctx context.Context, ns v1.NamespaceName, id string) (DeadLetter, error)
	// Delete removes a record (discard / replay-success); absent is not an error.
	Delete(ctx context.Context, ns v1.NamespaceName, id string) error
	// SweepExpired is store-global (no ns) and iterates ALL namespaces: the TTL is global — it evicts
	// entries older than retention across every namespace — while the count cap is enforced per-namespace,
	// by grouping keys under each dl/<ns>/ prefix and evicting the oldest over-cap in each. retention<=0
	// disables the TTL; maxPerNS<=0 disables the cap. Returns the number of records evicted.
	SweepExpired(ctx context.Context, retention time.Duration, maxPerNS int) (int, error)
	// Close releases the driver's resources.
	Close() error
}

Store is the dead-letter queue port (ADR-0002 §1) — bus-driver-independent. Records are engine-owned operational data, not a CRD. Implementations are the single source of truth for parked failures.

Directories

Path Synopsis
Package badger is the dead-letter-queue deadletter driver (ADR-0118), backed by Badger v4 in its own instance (never the metastore), which the event store shares with the blob seen lists (ADR-0201, NewOnDB).
Package badger is the dead-letter-queue deadletter driver (ADR-0118), backed by Badger v4 in its own instance (never the metastore), which the event store shares with the blob seen lists (ADR-0201, NewOnDB).
Package memory is the in-memory deadletter.Store driver (ADR-0118): a small pure-Go map with no files, for cross-platform tests and the InMemory preset.
Package memory is the in-memory deadletter.Store driver (ADR-0118): a small pure-Go map with no files, for cross-platform tests and the InMemory preset.

Jump to

Keyboard shortcuts

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