# `PgFlow.Runs`
[🔗](https://github.com/agoodway/pgflow/blob/v0.7.0/lib/pgflow/runs.ex#L1)

Typed operational reads for PgFlow runs, states, and tasks.

Every function receives the consumer repository explicitly so callers can
use their configured repository and tests can use an isolated repository.
Hosts that need SQL-level run-step progress can read the versioned
`pgflow.step_progress` view.

# `queue_location`

```elixir
@type queue_location() :: :all | :live | :archive
```

# `adjacent`

```elixir
@spec adjacent(module(), Ecto.UUID.t(), :next | :prev) ::
  {:ok, Ecto.UUID.t()} | {:error, :invalid_id | :invalid_direction | :not_found}
```

Gets the adjacent run UUID in newest-first navigation order.

`:next` selects the next older run and `:prev` selects the previous newer
run. Timestamp ties are resolved by UUID.

# `count`

```elixir
@spec count(module(), keyword()) :: {:ok, non_neg_integer()}
```

Counts runs matching the supplied filters.

Count ignores pagination options and accepts the same filter options as
`list/2`.

# `count_queue_messages`

```elixir
@spec count_queue_messages(
  module(),
  String.t() | atom(),
  Ecto.UUID.t() | [Ecto.UUID.t()],
  keyword()
) ::
  {:ok, non_neg_integer()}
  | {:error, :invalid_id | :invalid_flow_slug | :invalid_location | term()}
```

Counts durable PGMQ messages belonging to one or more run UUIDs.

The count uses persisted `(queue_name, message_id)` pairs from
`pgflow.step_tasks`, scoped to the requested flow slug. The `:location`
option accepts `:all` (the default), `:live`, or `:archive`. Missing queues
and an empty run-ID list both return `{:ok, 0}`.

# `delete`

```elixir
@spec delete(module(), Ecto.UUID.t()) ::
  :ok | {:error, :invalid_id | :invalid_flow_slug | term()}
```

Deletes a run's history: its lifecycle rows and its exact queue messages.

Delegates to `pgflow.delete_run(uuid)` in one statement, so Elixir and
SQL/Hasura callers share one implementation. The function locks the run,
then every task row of the run, before touching any queue, which keeps it
free of lock cycles with claims, stalled-task recovery, and pruning. Queue
cleanup uses each task's persisted `(queue_name, message_id)` identity in
both the live and archive tables, regardless of message age; a missing
queue table is skipped. Workers, flow definitions, queues, and unrelated
messages are left untouched.

This is a cleanup operation for history that may be discarded. It does not
interrupt a handler that is already running, and PgFlow has no per-run
cancel or fail API: a handler finishing after the delete finds no task to
complete.

An absent run is a successful no-op. A run whose persisted flow slug fails
PgFlow's slug rules returns `{:error, :invalid_flow_slug}` without deleting
anything; other database errors, including deadlocks and constraint
violations, are returned as `{:error, %Postgrex.Error{}}`.

## Examples

    :ok = PgFlow.Runs.delete(MyApp.Repo, run_id)

# `get`

```elixir
@spec get(module(), Ecto.UUID.t()) ::
  {:ok, PgFlow.Schema.Run.t()} | {:error, :invalid_id | :not_found}
```

Gets a persisted run by UUID.

# `get_step_task`

```elixir
@spec get_step_task(module(), Ecto.UUID.t(), String.t(), non_neg_integer()) ::
  {:ok, PgFlow.Schema.StepTask.t()} | {:error, :invalid_id | :not_found}
```

Gets one persisted task by run, step, and task index.

# `get_with_states`

```elixir
@spec get_with_states(module(), Ecto.UUID.t()) ::
  {:ok, PgFlow.Schema.Run.t()} | {:error, :invalid_id | :not_found}
```

Gets a persisted run with its step states preloaded in deterministic order.

# `history`

```elixir
@spec history(module(), String.t(), keyword()) :: {:ok, [PgFlow.RunHistoryCell.t()]}
```

Lists typed step-history cells for the most recent runs of a flow.

The `:limit` option controls how many runs are included, not the number of
returned cells.

# `list`

```elixir
@spec list(module(), keyword()) ::
  {:ok, [PgFlow.RunSummary.t()]} | {:error, :invalid_id}
```

Lists run summaries in newest-first order.

Supported options are `:flow_slug`, `:status`, `:flow_type`, `:time_range`,
`:started_after`, `:started_before`, `:input_contains`, `:cursor`, and `:limit`.
Explicit `:started_after` and `:started_before` bounds are inclusive. No time
filter is applied unless a time option is supplied.

# `list_run_tasks`

```elixir
@spec list_run_tasks(module(), Ecto.UUID.t()) ::
  {:ok, [PgFlow.Schema.StepTask.t()]} | {:error, :invalid_id}
```

Lists every persisted task for a run in step and task-index order.

# `list_step_states`

```elixir
@spec list_step_states(module(), Ecto.UUID.t()) ::
  {:ok, [PgFlow.Schema.StepState.t()]} | {:error, :invalid_id}
```

Lists a run's persisted step states in execution order.

# `list_step_tasks`

```elixir
@spec list_step_tasks(module(), Ecto.UUID.t(), String.t()) ::
  {:ok, [PgFlow.Schema.StepTask.t()]} | {:error, :invalid_id}
```

Lists all persisted tasks for a run step in task-index order.

# `make_available`

```elixir
@spec make_available(module(), Ecto.UUID.t()) ::
  :ok | {:error, :invalid_id | :invalid_flow_slug | term()}
```

Makes every queued task for a run immediately visible to workers.

Visibility updates are grouped by each task's persisted `queue_name` and
scoped to that task's `message_id`. An absent run or queue is a successful
no-op.

---

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