# `Outboxer.Envelope`
[🔗](https://github.com/epinault/outboxer/blob/v0.1.0/lib/outboxer/envelope.ex#L1)

A stored outbox message, as handed to a relay.

The envelope is what `c:Outboxer.Relay.deliver/2` receives. `payload` is the
binary produced by `c:Outboxer.Message.encode/1`; Outboxer never looks inside it.

`attempts` is the number of failed delivery attempts so far and `last_error`
the reason for the most recent one, so both are `0` and `nil` on a first try.

# `t`

```elixir
@type t() :: %Outboxer.Envelope{
  attempts: non_neg_integer(),
  group_key: String.t() | nil,
  headers: %{optional(String.t()) =&gt; String.t()},
  id: pos_integer(),
  inserted_at: DateTime.t() | nil,
  last_error: String.t() | nil,
  outbox: atom(),
  partition: non_neg_integer(),
  payload: binary(),
  type: String.t()
}
```

# `dedup_id`

```elixir
@spec dedup_id(t()) :: String.t()
```

A stable identifier for this message, suitable as an idempotency or
deduplication key on the consuming side.

Delivery is at-least-once, so a consumer can see the same message twice. The
id is the same on every attempt.

    iex> Outboxer.Envelope.dedup_id(%Outboxer.Envelope{id: 42, outbox: :orders, type: "t", payload: ""})
    "orders-42"

---

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