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

The behaviour every outbox message implements.

A message is a plain struct. `use Outboxer.Message` gives it sensible
defaults for every callback, so the smallest message is:

    defmodule MyApp.Events.OrderPlaced do
      use Outboxer.Message, outbox: :orders

      defstruct [:order_id, :total]
    end

and a message that takes part in ordered delivery adds a group key:

    defmodule MyApp.Events.OrderPlaced do
      use Outboxer.Message, outbox: :orders, type: "order.placed"

      defstruct [:order_id, :total]

      @impl true
      def group_key(%__MODULE__{order_id: id}), do: "order:#{id}"
    end

## Options for `use`

  * `:outbox` - the outbox this message is published to. Can be overridden
    per call with `Outboxer.publish(msg, outbox: :other)`.
  * `:type` - the type string stored with the message and passed to the
    relay. Defaults to the module name without the `Elixir.` prefix.

## Callbacks and their defaults

| Callback | Default |
| --- | --- |
| `c:outbox/0` | the `:outbox` option, or `nil` (then you must pass `outbox:` to `publish`) |
| `c:type/0` | the `:type` option, or the module name |
| `c:encode/1` | `JSON.encode!/1` of the struct's fields |
| `c:group_key/1` | `nil` (unordered) |
| `c:headers/1` | `%{}` |

## Encoding

The payload is stored as an opaque binary, so `c:encode/1` may return JSON,
Protobuf, Avro or anything else. The default uses Elixir's built-in `JSON`
module on `Map.from_struct/1`; if your struct holds values `JSON` cannot
encode (other structs without a `JSON.Encoder` implementation, tuples, pids)
implement `c:encode/1` yourself.

# `encode`

```elixir
@callback encode(message :: struct()) :: binary()
```

Serialises the message to the binary that will be stored and relayed.

# `group_key`

```elixir
@callback group_key(message :: struct()) :: String.t() | nil
```

The ordering group of the message, or `nil` when it does not need ordering.

Messages with the same group key in the same outbox are delivered in the
order they were published. See the "Ordering and groups" guide.

# `headers`

```elixir
@callback headers(message :: struct()) :: %{optional(String.t()) =&gt; String.t()}
```

String headers stored with the message and passed to the relay.

# `outbox`

```elixir
@callback outbox() :: atom() | nil
```

The outbox this message goes to by default.

# `type`

```elixir
@callback type() :: String.t()
```

A stable type name for this kind of message.

---

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