mirror of
https://github.com/ash-project/reactor.git
synced 2024-09-19 12:53:19 +12:00
docs: Add option schemas to public API functions and improve docs.
This commit is contained in:
parent
27a01e7862
commit
9a761a69c6
8 changed files with 168 additions and 12 deletions
|
@ -1,5 +1,5 @@
|
||||||
defmodule Reactor do
|
defmodule Reactor do
|
||||||
alias Reactor.{Dsl, Executor, Step}
|
alias Reactor.{Dsl, Error.Validation.StateError, Executor, Step}
|
||||||
|
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Reactor is a dynamic, concurrent, dependency resolving saga orchestrator.
|
Reactor is a dynamic, concurrent, dependency resolving saga orchestrator.
|
||||||
|
@ -129,13 +129,58 @@ defmodule Reactor do
|
||||||
steps: [Step.t()]
|
steps: [Step.t()]
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc false
|
@doc "A guard which returns true if the value is a Reactor struct"
|
||||||
@spec is_reactor(any) :: Macro.t()
|
@spec is_reactor(any) :: Macro.t()
|
||||||
defguard is_reactor(reactor) when is_struct(reactor, __MODULE__)
|
defguard is_reactor(reactor) when is_struct(reactor, __MODULE__)
|
||||||
|
|
||||||
|
@option_schema [
|
||||||
|
max_concurrency: [
|
||||||
|
type: :pos_integer,
|
||||||
|
required: false,
|
||||||
|
doc: "The maximum number of processes to use to run the Reactor"
|
||||||
|
],
|
||||||
|
timeout: [
|
||||||
|
type: {:or, [:pos_integer, {:literal, :infinity}]},
|
||||||
|
required: false,
|
||||||
|
default: :infinity,
|
||||||
|
doc: "How long to allow the Reactor to run for"
|
||||||
|
],
|
||||||
|
max_iterations: [
|
||||||
|
type: {:or, [:pos_integer, {:literal, :infinity}]},
|
||||||
|
required: false,
|
||||||
|
default: :infinity,
|
||||||
|
doc: "The maximum number of times to allow the Reactor to loop"
|
||||||
|
],
|
||||||
|
async_option: [
|
||||||
|
type: :boolean,
|
||||||
|
required: false,
|
||||||
|
default: true,
|
||||||
|
doc: "Whether to allow the Reactor to start processes"
|
||||||
|
],
|
||||||
|
concurrency_key_option: [
|
||||||
|
type: :reference,
|
||||||
|
required: false,
|
||||||
|
hide: true
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Run a reactor.
|
Attempt to run a Reactor.
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
* `reactor` - The Reactor to run, either a Reactor DSL module, or a Reactor
|
||||||
|
struct.
|
||||||
|
* `inputs` - A map of values passed in to satisfy the Reactor's expected
|
||||||
|
inputs.
|
||||||
|
* `context` - An arbitrary map that will be merged into the Reactor context
|
||||||
|
and passed into each step.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
#{Spark.Options.docs(@option_schema)}
|
||||||
"""
|
"""
|
||||||
|
@doc spark_opts: [{4, @option_schema}]
|
||||||
@spec run(t | module, inputs, context_arg, options) :: {:ok, any} | {:error, any} | {:halted, t}
|
@spec run(t | module, inputs, context_arg, options) :: {:ok, any} | {:error, any} | {:halted, t}
|
||||||
def run(reactor, inputs \\ %{}, context \\ %{}, options \\ [])
|
def run(reactor, inputs \\ %{}, context \\ %{}, options \\ [])
|
||||||
|
|
||||||
|
@ -152,4 +197,24 @@ defmodule Reactor do
|
||||||
when is_reactor(reactor) and reactor.state in ~w[pending halted]a do
|
when is_reactor(reactor) and reactor.state in ~w[pending halted]a do
|
||||||
Executor.run(reactor, inputs, context, options)
|
Executor.run(reactor, inputs, context, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run(reactor, _inputs, _context, _options) do
|
||||||
|
{:error,
|
||||||
|
StateError.exception(
|
||||||
|
reactor: reactor,
|
||||||
|
state: reactor.state,
|
||||||
|
expected: ~w[pending halted]a
|
||||||
|
)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "Raising version of `run/4`."
|
||||||
|
@spec run!(t | module, inputs, context_arg, options) :: any | no_return
|
||||||
|
def run!(reactor, inputs \\ %{}, context \\ %{}, options \\ [])
|
||||||
|
|
||||||
|
def run!(reactor, inputs, context, options) do
|
||||||
|
case run(reactor, inputs, context, options) do
|
||||||
|
{:ok, value} -> {:ok, value}
|
||||||
|
{:error, reason} -> raise reason
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,7 @@ defmodule Reactor.Builder do
|
||||||
import Reactor, only: :macros
|
import Reactor, only: :macros
|
||||||
import Reactor.Utils
|
import Reactor.Utils
|
||||||
|
|
||||||
@type step_options :: [async? | max_retries() | arguments_transform | context | ref]
|
@type step_options :: [async? | max_retries | arguments_transform | context | ref]
|
||||||
|
|
||||||
@typedoc "Should the step be run asynchronously?"
|
@typedoc "Should the step be run asynchronously?"
|
||||||
@type async? :: {:async?, boolean | (keyword -> boolean)}
|
@type async? :: {:async?, boolean | (keyword -> boolean)}
|
||||||
|
|
|
@ -9,9 +9,54 @@ defmodule Reactor.Builder.Step do
|
||||||
import Reactor.Argument, only: :macros
|
import Reactor.Argument, only: :macros
|
||||||
import Reactor.Utils
|
import Reactor.Utils
|
||||||
|
|
||||||
|
@option_schema [
|
||||||
|
async?: [
|
||||||
|
type: :boolean,
|
||||||
|
default: true,
|
||||||
|
required: false,
|
||||||
|
doc: "Allow the step to be run asynchronously?"
|
||||||
|
],
|
||||||
|
max_retries: [
|
||||||
|
type: {:or, [:non_neg_integer, {:literal, :infinity}]},
|
||||||
|
default: 100,
|
||||||
|
required: false,
|
||||||
|
doc: "The maximum number of times the step can ask to be retried"
|
||||||
|
],
|
||||||
|
transform: [
|
||||||
|
type: {:or, {:mfa_or_fun, 1}},
|
||||||
|
required: false,
|
||||||
|
doc: "A function which can modify all incoming arguments"
|
||||||
|
],
|
||||||
|
context: [
|
||||||
|
type: :map,
|
||||||
|
required: false,
|
||||||
|
doc: "Context which will be merged with the reactor context when calling this step"
|
||||||
|
],
|
||||||
|
ref: [
|
||||||
|
type: {:in, [:step_name, :make_ref]},
|
||||||
|
required: false,
|
||||||
|
default: :make_ref,
|
||||||
|
doc: "What sort of step reference to generate"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Build and add a new step to a Reactor.
|
Build and add a new step to a Reactor.
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
* `reactor` - An existing Reactor struct to add the step to.
|
||||||
|
* `name` - The proposed name of the new step.
|
||||||
|
* `impl` - A module implementing the `Reactor.Step` behaviour (or a tuple
|
||||||
|
containing the module and options).
|
||||||
|
* `arguments` - A list of `Reactor.Argument` structs or shorthand keyword
|
||||||
|
lists.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
#{Spark.Options.docs(@option_schema)}
|
||||||
"""
|
"""
|
||||||
|
@doc spark_opts: [{5, @option_schema}]
|
||||||
@spec add_step(
|
@spec add_step(
|
||||||
Reactor.t(),
|
Reactor.t(),
|
||||||
any,
|
any,
|
||||||
|
@ -65,7 +110,21 @@ defmodule Reactor.Builder.Step do
|
||||||
|
|
||||||
You're most likely to use this when dynamically returning new steps from an
|
You're most likely to use this when dynamically returning new steps from an
|
||||||
existing step.
|
existing step.
|
||||||
|
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
* `name` - The name of the new step.
|
||||||
|
* `impl` - A module implementing the `Reactor.Step` behaviour (or a tuple
|
||||||
|
containing the module and options).
|
||||||
|
* `arguments` - A list of `Reactor.Argument` structs or shorthand keyword
|
||||||
|
lists.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
#{Spark.Options.docs(@option_schema)}
|
||||||
"""
|
"""
|
||||||
|
@doc spark_opts: [{5, @option_schema}]
|
||||||
@spec new_step(any, Builder.impl(), [Builder.step_argument()], Builder.step_options()) ::
|
@spec new_step(any, Builder.impl(), [Builder.step_argument()], Builder.step_options()) ::
|
||||||
{:ok, Step.t()} | {:error, any}
|
{:ok, Step.t()} | {:error, any}
|
||||||
def new_step(name, impl, arguments, options) do
|
def new_step(name, impl, arguments, options) do
|
||||||
|
|
|
@ -2,8 +2,14 @@ defmodule Reactor.Step.AnonFn do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
The built-in step for executing in-line DSL anonymous functions.
|
The built-in step for executing in-line DSL anonymous functions.
|
||||||
|
|
||||||
This step assumes that it is being called as per the
|
## Options
|
||||||
`:spark_function_behaviour` semantics.
|
|
||||||
|
* `run` - a one or two arity function or MFA which will be called as the run
|
||||||
|
function of the step.
|
||||||
|
* `compensate` - a one to three arity function or MFA which will be called as
|
||||||
|
the compensate function of the step. Optional.
|
||||||
|
* `undo` - a one to three arity function or MFA which will be called as the
|
||||||
|
undo function of this step. Optional.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Reactor.Step
|
use Reactor.Step
|
||||||
|
|
|
@ -5,13 +5,18 @@ defmodule Reactor.Step.ComposeWrapper do
|
||||||
|
|
||||||
Yes, this gets hairy, fast.
|
Yes, this gets hairy, fast.
|
||||||
|
|
||||||
This is dynamically injected into steps by `Reactor.Step.Compose` - you
|
|
||||||
probably don't want to use this unless you're sure what you're doing.
|
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
* `original` - the original value of the Step's `impl` key.
|
* `original` - the original value of the Step's `impl` key.
|
||||||
* `prefix` - a list of values to be placed in the `name` before the original value.
|
* `prefix` - a list of values to be placed in the `name` before the original
|
||||||
|
value.
|
||||||
|
|
||||||
|
> #### Tip {: .tip}
|
||||||
|
>
|
||||||
|
> This is dynamically injected into steps by `Reactor.Step.Compose`.
|
||||||
|
>
|
||||||
|
> Most likely you will never need to use this step directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Reactor.Step
|
use Reactor.Step
|
||||||
|
|
|
@ -2,8 +2,20 @@ defmodule Reactor.Step.Transform do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
The built-in step for executing input and argument transformations.
|
The built-in step for executing input and argument transformations.
|
||||||
|
|
||||||
This step assumes that it is being executed as per `:spark_function_behaviour`
|
Expects a single argument named `value` which contains the value to be
|
||||||
semantics.
|
transformed.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
* `fun` - a one or two arity function or MFA to use to modify the `value`
|
||||||
|
argument.
|
||||||
|
|
||||||
|
> #### Tip {: .tip}
|
||||||
|
>
|
||||||
|
> This step is emitted by the builder when an argument needs to be transformed
|
||||||
|
> before being passed into a step.
|
||||||
|
>
|
||||||
|
> Most likely you will never need to use this step directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias Reactor.{Error.Invalid.MissingArgumentError, Error.Invalid.TransformError, Step}
|
alias Reactor.{Error.Invalid.MissingArgumentError, Error.Invalid.TransformError, Step}
|
||||||
|
|
|
@ -4,6 +4,14 @@ defmodule Reactor.Step.TransformAll do
|
||||||
|
|
||||||
The returned map is used as the arguments to the step, instead of the step's
|
The returned map is used as the arguments to the step, instead of the step's
|
||||||
defined arguments.
|
defined arguments.
|
||||||
|
|
||||||
|
|
||||||
|
> #### Tip {: .tip}
|
||||||
|
>
|
||||||
|
> This step will be emitted by the builder when a step wants to transform all
|
||||||
|
> it's arguments.
|
||||||
|
>
|
||||||
|
> Most likely you will never need to use this step directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Reactor.Step
|
use Reactor.Step
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -38,9 +38,10 @@ defmodule Reactor.MixProject do
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
groups_for_modules: [
|
groups_for_modules: [
|
||||||
DSL: ~r/^Reactor\.Dsl$/,
|
Dsl: ~r/^Reactor\.Dsl.*/,
|
||||||
Steps: ~r/^Reactor\.Step.*/,
|
Steps: ~r/^Reactor\.Step.*/,
|
||||||
Middleware: ~r/^Reactor\.Middleware.*/,
|
Middleware: ~r/^Reactor\.Middleware.*/,
|
||||||
|
Errors: ~r/^Reactor\.Error.*/,
|
||||||
Builder: ~r/^Reactor\.Builder.*/,
|
Builder: ~r/^Reactor\.Builder.*/,
|
||||||
Internals: ~r/^Reactor\..*/
|
Internals: ~r/^Reactor\..*/
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue