DSL macros for declaring flows. Pulled in via use Caravela.Flow.
defmodule MyApp.Flows.BookSyncFlow do
use Caravela.Flow
flow :sync_book, initial_state: %{dirty: false, book_id: nil} do
repeat do
wait_until fn state -> state.dirty end
debounce 500
sequence do
set_state fn state -> %{state | dirty: :processing} end
run fn state ->
case MyApp.ExternalAPI.sync_book(state.book_id) do
:ok -> {:ok, %{state | dirty: false}}
{:error, :timeout} -> {:retry, state}
{:error, reason} -> {:error, reason}
end
end,
retries: 3, backoff: :exponential, base_delay: 200
end
end
end
endEvery flow/3 declaration compiles into two lookup functions:
__caravela_flow__/1— returns the compiled step tree for the given flow name.__caravela_flow_initial_state__/1— returns the default initial-state map.
__caravela_flows__/0 lists every declared name.
Summary
Functions
Pause until state has been stable for ms milliseconds.
Iterate the collection at state[key]. For each item, call
fun.(item, state); returning {:ok, new_state} threads the result
to the next iteration.
Declare a flow.
Run a dynamic list of zero-arity funs concurrently. Collect every
return value under the collect_as state key.
Run zero-arity funs concurrently, keep the first to return.
Repeat block. Runs the inner block forever.
Run fun.(state) once, with optional retry/backoff.
Sequence block. Runs inner steps in order.
Synchronously replace state via fun.(state).
Pause for ms milliseconds.
Block until fun.(state) returns truthy.
Functions
Pause until state has been stable for ms milliseconds.
Iterate the collection at state[key]. For each item, call
fun.(item, state); returning {:ok, new_state} threads the result
to the next iteration.
Declare a flow.
flow :name, initial_state: %{...} do
...
endThe block is compiled into a step tree consumed by
Caravela.Flow.Runner.
Run a dynamic list of zero-arity funs concurrently. Collect every
return value under the collect_as state key.
parallel fn state -> Enum.map(state.urls, &fetch_fn/1) end, collect_as: :fetched
Run zero-arity funs concurrently, keep the first to return.
race [fn -> api_a() end, fn -> api_b() end], collect_as: :winner
Repeat block. Runs the inner block forever.
Run fun.(state) once, with optional retry/backoff.
run fn state -> ... end, retries: 3, backoff: :exponential, base_delay: 200Accepted options:
:retries— how many retries on{:error, _}/{:retry, _}:backoff—:linear(default) or:exponential:base_delay— ms multiplier for retry delay (default100)
Sequence block. Runs inner steps in order.
Synchronously replace state via fun.(state).
Pause for ms milliseconds.
Block until fun.(state) returns truthy.