PgFlow.Runs (PgFlow v0.7.0)

Copy Markdown View Source

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.

Summary

Functions

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

Counts runs matching the supplied filters.

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

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

Gets a persisted run by UUID.

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

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

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

Lists run summaries in newest-first order.

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

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

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

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

Types

queue_location()

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

Functions

adjacent(repo, run_id, direction)

@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(repo, opts \\ [])

@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(repo, flow_slug, run_ids, opts \\ [])

@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(repo, run_id)

@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(repo, run_id)

@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(repo, run_id, step_slug, task_index)

@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(repo, run_id)

@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(repo, flow_slug, opts \\ [])

@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(repo, opts \\ [])

@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(repo, run_id)

@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(repo, run_id)

@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(repo, run_id, step_slug)

@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(repo, run_id)

@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.