+++ title = "Announcing Reactor" date = "2023-05-10" [taxonomies] tags = ["elixir", "ash", "reactor", "saga", "library"] [extra] cover_image = "reactor.jpg" +++ > This post is mirrored from it's original location on [dev.to](https://dev.to/jimsy/towards-an-ethical-open-source-license-2fco). I'm excited to announce the first release of [Reactor](https://hex.pm/packages/reactor) - we've extracted the core ideas from `Ash.Engine` into it's own package, added compensation and turned it into a dynamic, concurrent, dependency resolving saga orchestrator. With reactor you break up your workflow into a bunch of [steps](https://hexdocs.pm/reactor/Reactor.Step.html) and define the dependencies between then using arguments. Reactor will calculate the dependencies and run steps concurrency as their dependencies are fulfilled until there are no more steps left running. Here's an example of a very simple step: ```elixir defmodule Greeter do use Reactor.Step def run(%{whom: nil}, _, _), do: {:ok, "Hello, World!"} def run(%{whom: whom}, _, _), do: {:ok, "Hello, #{whom}!"} end ``` You can construct a Reactor statically using a nice DSL ```elixir defmodule HelloWorldReactor do use Reactor input :whom step :greet, Greeter do argument :whom, input(:whom) end return :greet end ``` iex> Reactor.run(HelloWorldReactor, %{whom: "Dear Reader"}) {:ok, "Hello, Dear Reader!"} or you can build it programmatically: iex> reactor = Builder.new() ...> {:ok, reactor} = Builder.add_input(reactor, :whom) ...> {:ok, reactor} = Builder.add_step(reactor, :greet, Greeter, whom: {:input, :whom}) ...> {:ok, reactor} = Builder.return(reactor, :greet) ...> Reactor.run(reactor, %{whom: nil}) {:ok, "Hello, World!"} ## Rollback If any step fails and it defines the `compensate/4` callback, Reactor will call the compensation function, giving the step the opportunity to recover, retry or clean up after itself. If the step is unable to recover, then any previously executed steps which define the `undo/4` callback will be called. This allows for transaction-like semantics even when working with multiple disparate resources. ## Summary Shipping Reactor was a huge undertaking and I'm very proud of the result. Both [Zach](https://genserver.social/zachdaniel) and I are very eager to start using it to replace the existing `Ash.Engine` and unlocking new features of the Ash community. ## Links - [hex.pm/packages/reactor](https://hex.pm/packages/reactor) - [hexdocs.pm/reactor](https://hexdocs.pm/reactor/readme.html) - [github.com/ash-project/reactor](https://github.com/ash-project/reactor) - [Getting Started Guide](https://hexdocs.pm/reactor/getting-started-with-reactor.html) - [ash-hq.com](https://ash-hq.com) - [Ash Discord](https://discord.gg/NnkhUmkv)