Caravela.Flow.DSL (Caravela v0.13.1)

Copy Markdown View Source

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
end

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

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

debounce(ms)

(macro)

Pause until state has been stable for ms milliseconds.

each(key, fun)

(macro)

Iterate the collection at state[key]. For each item, call fun.(item, state); returning {:ok, new_state} threads the result to the next iteration.

flow(name, opts \\ [], list)

(macro)

Declare a flow.

flow :name, initial_state: %{...} do
  ...
end

The block is compiled into a step tree consumed by Caravela.Flow.Runner.

parallel(fun, opts \\ [])

(macro)

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

race(tasks, opts \\ [])

(macro)

Run zero-arity funs concurrently, keep the first to return.

race [fn -> api_a() end, fn -> api_b() end], collect_as: :winner

repeat(list)

(macro)

Repeat block. Runs the inner block forever.

run(fun, opts \\ [])

(macro)

Run fun.(state) once, with optional retry/backoff.

run fn state -> ... end, retries: 3, backoff: :exponential, base_delay: 200

Accepted options:

  • :retries — how many retries on {:error, _} / {:retry, _}
  • :backoff:linear (default) or :exponential
  • :base_delay — ms multiplier for retry delay (default 100)

sequence(list)

(macro)

Sequence block. Runs inner steps in order.

set_state(fun)

(macro)

Synchronously replace state via fun.(state).

wait(ms)

(macro)

Pause for ms milliseconds.

wait_until(fun)

(macro)

Block until fun.(state) returns truthy.