# `DDD.Outbox.DeadLetters`
[🔗](https://github.com/blackuprise/vicander/blob/v0.1.1/lib/ddd/events/outbox/dead_letters.ex#L1)

Inspect and resolve dead-lettered outbox events.

An event is dead-lettered when delivery kept failing (an infrastructure error, an exception,
an event type that can't be resolved) and the poller ran out of retries. Business rejections
are *not* dead letters: they are recorded as `rejected` in `event_deliveries`.

A dead letter is *unresolved* until someone decides what to do with it:

  * `replay/2`  - clear the failure state; the poller retries it. Handlers that already
    succeeded for the event are skipped.
  * `keep/2`    - acknowledge it and leave it dead-lettered (nothing more will happen).
  * `discard/2` - drop it for good.

`DDD.Outbox.DeadLetterHandler` applies a policy to new dead letters automatically; the
`mix vic.outbox.*` tasks call these functions for manual work.

# `dead_letter`

```elixir
@type dead_letter() :: %{
  id: String.t(),
  event_type: String.t(),
  aggregate_type: String.t(),
  aggregate_id: String.t(),
  payload: map(),
  attempts: non_neg_integer(),
  last_error: String.t() | nil,
  failed_at: DateTime.t(),
  resolution: String.t() | nil,
  resolved_at: DateTime.t() | nil,
  replays: non_neg_integer()
}
```

# `discard`

```elixir
@spec discard(module(), String.t()) :: :ok | {:error, :not_found}
```

Resolve the dead letter as discarded.

# `get`

```elixir
@spec get(module(), String.t()) :: dead_letter() | nil
```

One dead letter by its UUID string, or `nil`.

# `keep`

```elixir
@spec keep(module(), String.t()) :: :ok | {:error, :not_found}
```

Acknowledge the dead letter and leave it as it is.

# `list`

```elixir
@spec list(module(), keyword()) :: [dead_letter()]
```

Dead letters, oldest first. Only unresolved ones unless `all: true`. `limit:` defaults to 100.

# `replay`

```elixir
@spec replay(module(), String.t()) :: :ok | {:error, :not_found}
```

Make the poller retry the event from scratch. Counts in `replays`.

# `replay_all`

```elixir
@spec replay_all(module()) :: non_neg_integer()
```

Replay every unresolved dead letter. Returns how many were replayed.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
