# `Mailglass.Oban.TenancyMiddleware`
[🔗](https://github.com/szTheory/mailglass/blob/v0.1.0/lib/mailglass/optional_deps/oban.ex#L88)

Serializes `Mailglass.Tenancy.current/0` across Oban job boundaries (D-33).

## Enqueue side

Phase 3 `Mailglass.Outbound` adds a `put_tenant_in_args/2` helper that
merges `%{"mailglass_tenant_id" => current()}` into job args at enqueue
time. The serialized value is a plain string — JSON-safe, no coercion.

## Perform side

Two equivalent integration paths — both converge on
`Mailglass.Tenancy.with_tenant/2`.

### OSS Oban (`wrap_perform/2`)

OSS Oban 2.21 has no middleware behaviour. Adopters wrap their worker's
`perform/1` body:

    defmodule MyApp.MailerWorker do
      use Oban.Worker

      @impl Oban.Worker
      def perform(job) do
        Mailglass.Oban.TenancyMiddleware.wrap_perform(job, fn ->
          # ... worker body; Mailglass.Tenancy.current/0 now returns
          # the tenant stamped at enqueue time.
          :ok
        end)
      end
    end

### Oban Pro (`call/2`)

Oban Pro's `Oban.Middleware` behaviour invokes `call/2`. The shape this
module exports matches the documented behaviour (`job` + `next/1`
continuation) so Pro adopters register it directly:

    config :my_app, Oban,
      engine: Oban.Engines.Basic,
      middleware: [Mailglass.Oban.TenancyMiddleware],
      queues: [mailglass: 10]

## Contract

- `job.args["mailglass_tenant_id"]` present and binary → wrap in
  `Mailglass.Tenancy.with_tenant/2`.
- Key missing or non-binary → pass through unchanged. Lets adopters
  phase in the middleware without breaking existing jobs.
- If the wrapped body raises, the prior tenant stamp is restored
  before the raise propagates (inherited from
  `Mailglass.Tenancy.with_tenant/2`).

# `call`
*since 0.1.0* 

```elixir
@spec call(map(), (map() -&gt; any())) :: any()
```

Oban-Pro-compatible middleware entry point.

`next/1` is the continuation supplied by Pro's middleware stack;
receives the job and returns the perform result. For OSS adopters,
prefer `wrap_perform/2`.

# `wrap_perform`
*since 0.1.0* 

```elixir
@spec wrap_perform(map(), (-&gt; any())) :: any()
```

Wraps `fun` in `Mailglass.Tenancy.with_tenant/2` when `job.args` carries
a binary `"mailglass_tenant_id"`. Pass-through otherwise.

This is the OSS-Oban-friendly integration surface — adopters invoke it
from inside their `perform/1`. `fun` is zero-arity; the job struct is
available in the closure the caller constructs.

---

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