Skip to main content

lib/ferric_store/workflow.ex

defmodule FerricStore.Workflow do
  @moduledoc """
  State-machine workflow convenience API.

  This layer keeps workflows explicit: start a flow in a state, claim due work,
  transition to the next state, or finish with complete/fail/retry.
  """

  alias FerricStore.Flow

  defstruct [
    :client,
    :type,
    initial_state: "queued",
    worker: "elixir-workflow",
    lease_ms: 30_000,
    codec: FerricStore.Codec.Raw
  ]

  def new(client, type, opts \\ []) do
    struct(__MODULE__, Keyword.merge([client: client, type: type], opts))
  end

  def start(%__MODULE__{} = workflow, id, opts \\ []) do
    Flow.create(
      workflow.client,
      id,
      Keyword.merge(
        [type: workflow.type, state: workflow.initial_state, codec: workflow.codec],
        opts
      )
    )
  end

  def claim(%__MODULE__{} = workflow, state, opts \\ []) do
    Flow.claim_due(
      workflow.client,
      workflow.type,
      Keyword.merge([state: state, worker: workflow.worker, lease_ms: workflow.lease_ms], opts)
    )
  end

  def transition(%__MODULE__{} = workflow, id, from_state, to_state, opts) do
    Flow.transition(
      workflow.client,
      id,
      Keyword.merge([from_state: from_state, to_state: to_state, codec: workflow.codec], opts)
    )
  end

  def complete(%__MODULE__{} = workflow, id, opts) do
    Flow.complete(workflow.client, id, Keyword.merge([codec: workflow.codec], opts))
  end

  def retry(%__MODULE__{} = workflow, id, opts) do
    Flow.retry(workflow.client, id, Keyword.merge([codec: workflow.codec], opts))
  end

  def fail(%__MODULE__{} = workflow, id, opts) do
    Flow.fail(workflow.client, id, Keyword.merge([codec: workflow.codec], opts))
  end
end