deadletter

package
v0.6.2 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 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  time.Time        `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 a DEDICATED instance (never the metastore).
Package badger is the dead-letter-queue deadletter driver (ADR-0118), backed by Badger v4 in a DEDICATED instance (never the metastore).
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