# `PhoenixKit.Jobs.ObanStore`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.55.1/lib/phoenix_kit/jobs/oban_store.ex#L1)

Reads of Oban's own `oban_jobs` table, routed the way Oban routes them.

`Oban.Job` carries no PhoenixKit `@schema_prefix`, so `Repo.get(Oban.Job, id)`
reads the connection's default schema — the wrong table on an install whose
Oban lives in a named schema (`config :app, Oban, prefix: "..."`), and a table
that may not exist at all. Oban inserts a dispatch with its configured prefix;
everything that looks at the dispatch again must go through the same
configuration. This module is the one place that does.

**The prefix is known only from a running Oban instance.** Where none runs in
this VM (a script, a web-only node), this module does not guess: a dispatch
lookup answers `:unavailable`, and a listing answers the default the caller
gave. It never falls back to a raw query on the repo, which would read the
default schema — a different table. A database error while reading the *right*
table is not "unavailable"; it is raised.

# `aggregate`

```elixir
@spec aggregate(Ecto.Queryable.t(), :count | :sum | :avg | :min | :max, term()) ::
  term()
```

`Oban.Repo.aggregate/3` for `query`; `default` when Oban cannot be asked.

# `all`

```elixir
@spec all(Ecto.Queryable.t(), list()) :: list()
```

`Oban.Repo.all/2` for `query`; `default` when Oban cannot be asked.

# `available?`

```elixir
@spec available?() :: boolean()
```

Whether an Oban instance runs in this VM, so that its table can be read.

# `dispatch_of`

```elixir
@spec dispatch_of(PhoenixKit.Jobs.Run.t()) :: Oban.Job.t() | nil | :unavailable
```

The Oban job `id` as the current dispatch of `run`, or `nil` when there is none
that belongs to it: never made, pruned, or a row of another worker, run or
generation (an integer id alone proves nothing). `:unavailable` when Oban cannot
be asked — **including for a run that has no job id**: whether a dispatch is
missing cannot be judged while nothing could have made one.

# `one`

```elixir
@spec one(Ecto.Queryable.t(), term()) :: term()
```

`Oban.Repo.one/2` for `query`; `default` when Oban cannot be asked.

# `stalled_queues`

```elixir
@spec stalled_queues(non_neg_integer(), DateTime.t()) :: [String.t()]
```

The queues that look dead: an active run's current dispatch has been `available`
for `after_seconds` (default ten minutes) and **nothing in that queue has executed
or attempted a job in that time**. Paused runs and obsolete generations do not
need dispatch and cannot make a queue look stalled. Observed from Oban's own
table — a web node with `queues: false` proves nothing about a separate worker
node, and this reads what the nodes actually did. Empty when Oban cannot be asked.

# `state_counts`

```elixir
@spec state_counts() :: %{required(String.t()) =&gt; non_neg_integer()}
```

The Oban job counts by state (empty when Oban cannot be asked).

---

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