# `Letterbox.Runner`
[🔗](https://github.com/hattoriai/letterbox/blob/v0.1.0-rc.0/lib/letterbox/runner.ex#L1)

What runs Letterbox's work out of the request: fetching a message its
provider told of, and giving each message to its mailbox. One runner does
all of it, and another takes its place with no other change.

  * `Letterbox.Runner.Oban` - in Oban jobs, kept in the app's database:
    work that outlives a deploy, tried again with Oban's backoff. The
    default when the app runs Oban (an instance named `Oban`).
  * `Letterbox.Runner.Local` - in a process of Letterbox's, tried again
    with backoff. The default otherwise. Work it had when the app stopped
    is not lost: each message's state is in its row, and
    `Letterbox.resume/0` (or `Letterbox.Sweeper`) gives it to the runner
    again.
  * `:inline` - in the caller, at once: for tests (`Letterbox.Test`).
  * A module of the app's, of this behaviour.

## Choosing it

    config :letterbox, runner: Letterbox.Runner.Oban
    config :letterbox, Letterbox.Runner.Oban, queue: :mail, name: MyApp.Oban

## Writing one

A runner keeps a job, a map that JSON holds (`%{"work" => "process",
"id" => "…"}`), and runs it with `Letterbox.Runner.run/1` until it gives
`:ok`, at most `Letterbox.Config`'s `:max_attempts` times.

# `t`

```elixir
@type t() :: module() | {module(), keyword()} | :oban | :local | :inline
```

A runner: a module, `{module, opts}`, or `:oban`, `:local` or `:inline`.

# `enqueue`

```elixir
@callback enqueue(job :: map(), opts :: keyword()) :: :ok | {:error, term()}
```

Keeps the job and runs it out of the caller: `:ok` once it is kept.

# `resolve`

```elixir
@spec resolve(t() | nil) :: {module(), keyword()} | :inline
```

The runner used: the one given, else `config :letterbox, :runner`, else
Oban's when an instance named `Oban` runs, else `Letterbox.Runner.Local`.

# `run`

```elixir
@spec run(map()) :: :ok | {:error, term()}
```

Runs a job once: `:ok`, or `{:error, reason}` to be tried again. A job
for a message that is gone is `:ok`.

---

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