reactor/documentation/dsls/DSL:-Reactor.md
James Harton 37b9eda48e
feat: Add telemetry middleware. (#93)
* improvement: don't incur compile-time dependencies on middleware.

* feat: Add a middleware which emits telemetry events about Reactor.
2024-02-29 09:23:51 +13:00

24 KiB

DSL: Reactor.Dsl

reactor

The top-level reactor DSL

Nested DSLs

Options

Name Type Default Docs
return{: #reactor-return } atom Specify which step result to return upon completion.

reactor.middlewares

Middleware to be added to the Reactor

Nested DSLs

reactor.middlewares.middleware

middleware module

Name a middleware to be added to the Reactor.

Arguments

Name Type Default Docs
module{: #reactor-middlewares-middleware-module .spark-required} module The middleware to be added to the Reactor.

Introspection

Target: Reactor.Dsl.Middleware

reactor.around

around name, fun \\ nil

Wrap a function around a group of steps.

Nested DSLs

Arguments

Name Type Default Docs
name{: #reactor-around-name .spark-required} atom A unique name of the group of steps.
fun{: #reactor-around-fun .spark-required} (any, any, any, any -> any) | mfa The around function. See Reactor.Step.Around for more information.

Options

Name Type Default Docs
allow_async?{: #reactor-around-allow_async? } boolean false Whether the emitted steps should be allowed to run asynchronously.

reactor.around.argument

argument name, source \\ nil

Specifies an argument to a Reactor step.

Each argument is a value which is either the result of another step, or an input value.

Individual arguments can be transformed with an arbitrary function before being passed to any steps.

Examples

argument :name, input(:name)

argument :year, input(:date, [:year])

argument :user, result(:create_user)

argument :user_id, result(:create_user) do
  transform & &1.id
end

argument :user_id, result(:create_user, [:id])

argument :three, value(3)

Arguments

Name Type Default Docs
name{: #reactor-around-argument-name .spark-required} atom The name of the argument which will be used as the key in the arguments map passed to the implementation.
source{: #reactor-around-argument-source .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value What to use as the source of the argument. See Reactor.Dsl.Argument for more information.

Options

Name Type Default Docs
transform{: #reactor-around-argument-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the argument before it is passed to the step.

Introspection

Target: Reactor.Dsl.Argument

reactor.around.wait_for

wait_for names

Wait for the named step to complete before allowing this one to start.

Desugars to argument :_, result(step_to_wait_for)

Examples

wait_for :create_user

Arguments

Name Type Default Docs
names{: #reactor-around-wait_for-names .spark-required} atom | list(atom) The name of the step to wait for.

Introspection

Target: Reactor.Dsl.WaitFor

Introspection

Target: Reactor.Dsl.Around

reactor.collect

collect name

A Reactor step which simply collects and returns it's arguments.

Arguments can optionally be transformed before returning.

Nested DSLs

Examples

collect :latest_release_uri do
  argument :repository, input(:repository)
  argument :organisation, input(:organisation)

  transform fn inputs ->
    %{uri: "https://api.github.com/repos/#{inputs.organisation}/#{inputs.repository}/releases/latest"}
  end
end

Arguments

Name Type Default Docs
name{: #reactor-collect-name .spark-required} atom A unique name for the step. Used when choosing the return value of the Reactor and for arguments into other steps.

Options

Name Type Default Docs
transform{: #reactor-collect-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the entire argument map before it is returned.

reactor.collect.argument

argument name, source \\ nil

Specifies an argument to a Reactor step.

Each argument is a value which is either the result of another step, or an input value.

Individual arguments can be transformed with an arbitrary function before being passed to any steps.

Examples

argument :name, input(:name)

argument :year, input(:date, [:year])

argument :user, result(:create_user)

argument :user_id, result(:create_user) do
  transform & &1.id
end

argument :user_id, result(:create_user, [:id])

argument :three, value(3)

Arguments

Name Type Default Docs
name{: #reactor-collect-argument-name .spark-required} atom The name of the argument which will be used as the key in the arguments map passed to the implementation.
source{: #reactor-collect-argument-source .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value What to use as the source of the argument. See Reactor.Dsl.Argument for more information.

Options

Name Type Default Docs
transform{: #reactor-collect-argument-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the argument before it is passed to the step.

Introspection

Target: Reactor.Dsl.Argument

reactor.collect.wait_for

wait_for names

Wait for the named step to complete before allowing this one to start.

Desugars to argument :_, result(step_to_wait_for)

Examples

wait_for :create_user

Arguments

Name Type Default Docs
names{: #reactor-collect-wait_for-names .spark-required} atom | list(atom) The name of the step to wait for.

Introspection

Target: Reactor.Dsl.WaitFor

Introspection

Target: Reactor.Dsl.Collect

reactor.compose

compose name, reactor

Compose another Reactor into this one.

Allows place another Reactor into this one as if it were a single step.

Nested DSLs

Arguments

Name Type Default Docs
name{: #reactor-compose-name .spark-required} atom A unique name for the step. Allows the result of the composed reactor to be depended upon by steps in this reactor.
reactor{: #reactor-compose-reactor .spark-required} Reactor | module The reactor module or struct to compose upon.

reactor.compose.argument

argument name, source \\ nil

Specifies an argument to a Reactor step.

Each argument is a value which is either the result of another step, or an input value.

Individual arguments can be transformed with an arbitrary function before being passed to any steps.

Examples

argument :name, input(:name)

argument :year, input(:date, [:year])

argument :user, result(:create_user)

argument :user_id, result(:create_user) do
  transform & &1.id
end

argument :user_id, result(:create_user, [:id])

argument :three, value(3)

Arguments

Name Type Default Docs
name{: #reactor-compose-argument-name .spark-required} atom The name of the argument which will be used as the key in the arguments map passed to the implementation.
source{: #reactor-compose-argument-source .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value What to use as the source of the argument. See Reactor.Dsl.Argument for more information.

Options

Name Type Default Docs
transform{: #reactor-compose-argument-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the argument before it is passed to the step.

Introspection

Target: Reactor.Dsl.Argument

reactor.compose.wait_for

wait_for names

Wait for the named step to complete before allowing this one to start.

Desugars to argument :_, result(step_to_wait_for)

Examples

wait_for :create_user

Arguments

Name Type Default Docs
names{: #reactor-compose-wait_for-names .spark-required} atom | list(atom) The name of the step to wait for.

Introspection

Target: Reactor.Dsl.WaitFor

Introspection

Target: Reactor.Dsl.Compose

reactor.debug

debug name

Inserts a step which will send debug information to the Logger.

Nested DSLs

Examples

debug :debug do
  argument :suss, result(:suss_step)
end

Arguments

Name Type Default Docs
name{: #reactor-debug-name .spark-required} atom A unique identifier for the step.

Options

Name Type Default Docs
level{: #reactor-debug-level } :emergency | :alert | :critical | :error | :warning | :notice | :info | :debug :debug The log level to send the debug information to.

reactor.debug.argument

argument name, source \\ nil

Specifies an argument to a Reactor step.

Each argument is a value which is either the result of another step, or an input value.

Individual arguments can be transformed with an arbitrary function before being passed to any steps.

Examples

argument :name, input(:name)

argument :year, input(:date, [:year])

argument :user, result(:create_user)

argument :user_id, result(:create_user) do
  transform & &1.id
end

argument :user_id, result(:create_user, [:id])

argument :three, value(3)

Arguments

Name Type Default Docs
name{: #reactor-debug-argument-name .spark-required} atom The name of the argument which will be used as the key in the arguments map passed to the implementation.
source{: #reactor-debug-argument-source .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value What to use as the source of the argument. See Reactor.Dsl.Argument for more information.

Options

Name Type Default Docs
transform{: #reactor-debug-argument-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the argument before it is passed to the step.

Introspection

Target: Reactor.Dsl.Argument

reactor.debug.wait_for

wait_for names

Wait for the named step to complete before allowing this one to start.

Desugars to argument :_, result(step_to_wait_for)

Examples

wait_for :create_user

Arguments

Name Type Default Docs
names{: #reactor-debug-wait_for-names .spark-required} atom | list(atom) The name of the step to wait for.

Introspection

Target: Reactor.Dsl.WaitFor

Introspection

Target: Reactor.Dsl.Debug

reactor.group

group name

Call functions before and after a group of steps.

Nested DSLs

Arguments

Name Type Default Docs
name{: #reactor-group-name .spark-required} atom A unique name for the group of steps.

Options

Name Type Default Docs
before_all{: #reactor-group-before_all .spark-required} (any, any, any -> any) | mfa The before function. See Reactor.Step.Group for more information.
after_all{: #reactor-group-after_all .spark-required} (any -> any) | mfa The after function. See Reactor.Step.Group for more information.
allow_async?{: #reactor-group-allow_async? } boolean true Whether the emitted steps should be allowed to run asynchronously.

reactor.group.argument

argument name, source \\ nil

Specifies an argument to a Reactor step.

Each argument is a value which is either the result of another step, or an input value.

Individual arguments can be transformed with an arbitrary function before being passed to any steps.

Examples

argument :name, input(:name)

argument :year, input(:date, [:year])

argument :user, result(:create_user)

argument :user_id, result(:create_user) do
  transform & &1.id
end

argument :user_id, result(:create_user, [:id])

argument :three, value(3)

Arguments

Name Type Default Docs
name{: #reactor-group-argument-name .spark-required} atom The name of the argument which will be used as the key in the arguments map passed to the implementation.
source{: #reactor-group-argument-source .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value What to use as the source of the argument. See Reactor.Dsl.Argument for more information.

Options

Name Type Default Docs
transform{: #reactor-group-argument-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the argument before it is passed to the step.

Introspection

Target: Reactor.Dsl.Argument

reactor.group.wait_for

wait_for names

Wait for the named step to complete before allowing this one to start.

Desugars to argument :_, result(step_to_wait_for)

Examples

wait_for :create_user

Arguments

Name Type Default Docs
names{: #reactor-group-wait_for-names .spark-required} atom | list(atom) The name of the step to wait for.

Introspection

Target: Reactor.Dsl.WaitFor

Introspection

Target: Reactor.Dsl.Group

reactor.input

input name

Specifies an input to the Reactor.

An input is a value passed in to the Reactor when executing. If a Reactor were a function, these would be it's arguments.

Inputs can be transformed with an arbitrary function before being passed to any steps.

Examples

input :name

input :age do
  transform &String.to_integer/1
end

Arguments

Name Type Default Docs
name{: #reactor-input-name .spark-required} atom A unique name for this input. Used to allow steps to depend on it.

Options

Name Type Default Docs
transform{: #reactor-input-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the input before it is passed to any steps.

Introspection

Target: Reactor.Dsl.Input

reactor.step

step name, impl \\ nil

Specifies a Reactor step.

Steps are the unit of work in a Reactor. Reactor will calculate the dependencies graph between the steps and execute as many as it can in each iteration.

See the Reactor.Step behaviour for more information.

Nested DSLs

Examples

step :create_user, MyApp.Steps.CreateUser do
  argument :username, input(:username)
  argument :password_hash, result(:hash_password)
end

step :hash_password do
  argument :password, input(:password)

  run fn %{password: password}, _ ->
    {:ok, Bcrypt.hash_pwd_salt(password)}
  end
end

Arguments

Name Type Default Docs
name{: #reactor-step-name .spark-required} atom A unique name for the step. Used when choosing the return value of the Reactor and for arguments into other steps.
impl{: #reactor-step-impl } module | nil A module that implements the Reactor.Step behaviour that provides the implementation.

Options

Name Type Default Docs
run{: #reactor-step-run } (any -> any) | mfa | (any, any -> any) | mfa Provide an anonymous function which implements the run/3 callback. Cannot be provided at the same time as the impl argument.
undo{: #reactor-step-undo } (any -> any) | mfa | (any, any -> any) | mfa | (any, any, any -> any) | mfa Provide an anonymous function which implements the undo/4 callback. Cannot be provided at the same time as the impl argument.
compensate{: #reactor-step-compensate } (any -> any) | mfa | (any, any -> any) | mfa | (any, any, any -> any) | mfa Provide an anonymous function which implements the undo/4 callback. Cannot be provided at the same time as the impl argument.
max_retries{: #reactor-step-max_retries } :infinity | non_neg_integer :infinity The maximum number of times that the step can be retried before failing. Only used when the result of the compensate/4 callback is :retry.
async?{: #reactor-step-async? } boolean true When set to true the step will be executed asynchronously via Reactor's TaskSupervisor.
transform{: #reactor-step-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the entire argument map before it is passed to the step.

reactor.step.argument

argument name, source \\ nil

Specifies an argument to a Reactor step.

Each argument is a value which is either the result of another step, or an input value.

Individual arguments can be transformed with an arbitrary function before being passed to any steps.

Examples

argument :name, input(:name)

argument :year, input(:date, [:year])

argument :user, result(:create_user)

argument :user_id, result(:create_user) do
  transform & &1.id
end

argument :user_id, result(:create_user, [:id])

argument :three, value(3)

Arguments

Name Type Default Docs
name{: #reactor-step-argument-name .spark-required} atom The name of the argument which will be used as the key in the arguments map passed to the implementation.
source{: #reactor-step-argument-source .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value What to use as the source of the argument. See Reactor.Dsl.Argument for more information.

Options

Name Type Default Docs
transform{: #reactor-step-argument-transform } (any -> any) | module | nil An optional transformation function which can be used to modify the argument before it is passed to the step.

Introspection

Target: Reactor.Dsl.Argument

reactor.step.wait_for

wait_for names

Wait for the named step to complete before allowing this one to start.

Desugars to argument :_, result(step_to_wait_for)

Examples

wait_for :create_user

Arguments

Name Type Default Docs
names{: #reactor-step-wait_for-names .spark-required} atom | list(atom) The name of the step to wait for.

Introspection

Target: Reactor.Dsl.WaitFor

Introspection

Target: Reactor.Dsl.Step

reactor.switch

switch name

Use a predicate to determine which steps should be executed.

Nested DSLs

Arguments

Name Type Default Docs
name{: #reactor-switch-name .spark-required} atom A unique name for the switch.

Options

Name Type Default Docs
on{: #reactor-switch-on .spark-required} Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value The value to match against.
allow_async?{: #reactor-switch-allow_async? } boolean true Whether the emitted steps should be allowed to run asynchronously.

reactor.switch.matches?

matches? predicate

A group of steps to run when the predicate matches.

Arguments

Name Type Default Docs
predicate{: #reactor-switch-matches?-predicate .spark-required} (any -> any) | mfa A one-arity function which is used to match the switch input. If the switch returns a truthy value, then the nested steps will be run.

Options

Name Type Default Docs
allow_async?{: #reactor-switch-matches?-allow_async? } boolean true Whether the emitted steps should be allowed to run asynchronously.
return{: #reactor-switch-matches?-return } atom Specify which step result to return upon completion.

Introspection

Target: Reactor.Dsl.Switch.Match

reactor.switch.default

If none of the matches? branches match the input, then the default steps will be run if provided.

Options

Name Type Default Docs
return{: #reactor-switch-default-return } atom Specify which step result to return upon completion.

Introspection

Target: Reactor.Dsl.Switch.Default

Introspection

Target: Reactor.Dsl.Switch