feat: Add collect step entity. (#53)

This change introduces the `collect` step entity to the DSL. It is simply a wrapper around `Reactor.Step.ReturnAllArguments`, but provides the convenience of being able to group together arguments into a single structure for passing into other steps.
This commit is contained in:
James Harton 2023-09-11 11:58:29 +12:00 committed by GitHub
parent 61d7d3422b
commit f67173b76f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 4 deletions

View file

@ -10,6 +10,8 @@ spark_locals_without_parens = [
around: 3,
async?: 1,
before_all: 1,
collect: 1,
collect: 2,
compensate: 1,
compose: 2,
compose: 3,

View file

@ -18,12 +18,13 @@ defmodule Reactor.Dsl do
],
entities: [
Dsl.Around.__entity__(),
Dsl.Collect.__entity__(),
Dsl.Compose.__entity__(),
Dsl.Debug.__entity__(),
Dsl.Group.__entity__(),
Dsl.Input.__entity__(),
Dsl.Step.__entity__(),
Dsl.Switch.__entity__(),
Dsl.Compose.__entity__()
Dsl.Switch.__entity__()
],
top_level?: true,
patchable?: true

View file

@ -0,0 +1,87 @@
defmodule Reactor.Dsl.Collect do
@moduledoc """
The struct used to store collect DSL entities.
See `d:Reactor.collect`.
"""
defstruct __identifier__: nil,
arguments: [],
name: nil,
transform: nil
alias Reactor.{Builder, Dsl, Step}
@type t :: %__MODULE__{
arguments: [Dsl.Argument.t()],
name: atom,
transform: nil | (any -> any),
__identifier__: any
}
@doc false
def __entity__,
do: %Spark.Dsl.Entity{
name: :collect,
describe: """
A Reactor step which simply collects and returns it's arguments.
Arguments can optionally be transformed before returning.
""",
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
"""
],
args: [:name],
target: __MODULE__,
identifier: :name,
entities: [arguments: [Dsl.Argument.__entity__(), Dsl.WaitFor.__entity__()]],
recursive_as: :steps,
schema: [
name: [
type: :atom,
required: true,
doc: """
A unique name for the step.
This is used when choosing the return value of the Reactor and for arguments into other steps.
"""
],
transform: [
type: {:or, [{:spark_function_behaviour, Step, {Step.TransformAll, 1}}, nil]},
required: false,
default: nil,
doc: """
An optional transformation function which can be used to modify the
entire argument map before it is returned.
"""
]
]
}
defimpl Dsl.Build do
def build(collect, reactor) do
Builder.add_step(
reactor,
collect.name,
Step.ReturnAllArguments,
collect.arguments,
async?: true,
max_retries: 1,
transform: collect.transform,
ref: :step_name
)
end
def verify(_collect, _dsl_state), do: :ok
def transform(_collect, dsl_state), do: {:ok, dsl_state}
end
end

View file

@ -66,7 +66,7 @@ defmodule Reactor.Dsl.Step do
"""
],
args: [:name, {:optional, :impl}],
target: Dsl.Step,
target: __MODULE__,
identifier: :name,
no_depend_modules: [:impl],
entities: [arguments: [Dsl.Argument.__entity__(), Dsl.WaitFor.__entity__()]],
@ -79,7 +79,7 @@ defmodule Reactor.Dsl.Step do
A unique name for the step.
This is used when choosing the return value of the Reactor and for arguments into
another step.
other steps.
"""
],
impl: [

View file

@ -0,0 +1,39 @@
defmodule Reactor.Dsl.CollectTest do
@moduledoc false
use ExUnit.Case, async: true
defmodule Noop do
@moduledoc false
use Reactor.Step
def run(_, context, _), do: {:ok, context.current_step.name}
end
defmodule CollectTransformReactor do
@moduledoc false
use Reactor
input :organisation
input :repository
collect :latest_release_uri do
argument :org, input(:organisation)
argument :repo, input(:repository)
transform &__MODULE__.do_transform/1
end
def do_transform(inputs) do
%{uri: "https://api.github.com/repos/#{inputs.org}/#{inputs.repo}/releases/latest"}
end
end
test "it works" do
assert {:ok, result} =
Reactor.run(CollectTransformReactor, %{
organisation: "ash-project",
repository: "reactor"
})
assert result.uri == "https://api.github.com/repos/ash-project/reactor/releases/latest"
end
end