Durable.Orchestration (Durable v0.1.0-rc)
View SourceWorkflow composition: call child workflows from parent steps.
Provides two primitives for composing workflows:
call_workflow/3— Start a child workflow and wait for its result (synchronous)start_workflow/3— Start a child workflow without waiting (fire-and-forget)
Usage
defmodule MyApp.OrderWorkflow do
use Durable
use Durable.Context
use Durable.Orchestration
workflow "process_order" do
step :charge_payment, fn data ->
case call_workflow(MyApp.PaymentWorkflow, %{"amount" => data.total},
timeout: hours(1)) do
{:ok, result} ->
{:ok, assign(data, :payment_id, result["payment_id"])}
{:error, reason} ->
{:error, reason}
end
end
step :send_email, fn data ->
{:ok, email_wf_id} = start_workflow(MyApp.EmailWorkflow,
%{"to" => data.email}, ref: :confirmation)
{:ok, assign(data, :email_workflow_id, email_wf_id)}
end
end
end
Summary
Functions
Injects orchestration functions into the calling module.
Starts a child workflow and waits for its result.
Starts a child workflow without waiting for its result (fire-and-forget).
Functions
Injects orchestration functions into the calling module.
Starts a child workflow and waits for its result.
The parent workflow will be suspended until the child completes or fails.
On resume, returns {:ok, result} or {:error, reason}.
Options
:ref- Reference name for idempotency (default: module name):timeout- Timeout in milliseconds:timeout_value- Value returned on timeout (default::child_timeout):queue- Queue for the child workflow (default: "default"):durable- Durable instance name (default: Durable)
What the parent sees on success
The result returned on success is the child workflow's entire final
context, not just its explicit outputs. This includes every
put_context/2 key the child set, plus the final step's return value.
If you need to expose only specific outputs, return a clean shape from the child's final step or pick only the keys you need in the parent:
case call_workflow(MyApp.PaymentWorkflow, %{"amount" => 100}) do
{:ok, %{"payment_id" => id}} -> {:ok, assign(data, :payment_id, id)}
{:error, reason} -> {:error, reason}
endExamples
case call_workflow(MyApp.PaymentWorkflow, %{"amount" => 100}, timeout: hours(1)) do
{:ok, result} -> {:ok, assign(data, :payment, result)}
{:error, reason} -> {:error, reason}
end
Starts a child workflow without waiting for its result (fire-and-forget).
Returns {:ok, child_id} immediately. The child runs independently.
Idempotent: if resumed, returns the same child_id without creating a duplicate.
Options
:ref- Reference name for idempotency (default: module name):queue- Queue for the child workflow (default: "default"):durable- Durable instance name (default: Durable)
Examples
{:ok, child_id} = start_workflow(MyApp.EmailWorkflow,
%{"to" => email}, ref: :welcome_email)