Skuld.Effects.Command (skuld v0.1.26)

View Source

Effect for dispatching commands through a unified pipeline.

Commands are structs representing mutations. The handler is a single function (command -> computation) that can route commands however it likes (pattern matching, map lookup, etc.). The returned computation can use other effects.

Example

defmodule MyCommandHandler do
  use Skuld.Syntax

  # Route via pattern matching
  def handle(%CreateTodo{title: title}) do
    comp do
      {:ok, todo} <- EctoPersist.insert(changeset(title))
      _ <- EventAccumulator.emit(%TodoCreated{id: todo.id})
      {:ok, todo}
    end
  end

  def handle(%DeleteTodo{id: id}) do
    comp do
      todo <- EctoPersist.get!(Todo, id)
      _ <- EctoPersist.delete(todo)
      _ <- EventAccumulator.emit(%TodoDeleted{id: id})
      :ok
    end
  end
end

# Use the Command effect
comp do
  {:ok, todo} <- Command.execute(%CreateTodo{title: "Buy milk"})
  todo
end
|> Command.with_handler(&MyCommandHandler.handle/1)
|> EctoPersist.with_handler(Repo)
|> EventAccumulator.with_handler()
|> Comp.run!()

Handler Function

The handler function has signature (command -> computation). The returned computation can use any other effects installed in the pipeline. Routing is entirely up to the handler - use pattern matching, map lookup, or any other approach.

Summary

Types

Function that takes a command and returns a computation

Functions

Install Command handler via catch clause syntax.

Execute a command through the effect system.

Install a command handler for a computation.

Types

command_handler()

@type command_handler() :: (struct() -> Skuld.Comp.Types.computation())

Function that takes a command and returns a computation

Functions

__handle__(comp, handler_fn)

Install Command handler via catch clause syntax.

Config is the handler function:

catch
  Command -> &MyHandler.handle/1

execute(command)

@spec execute(struct()) :: Skuld.Comp.Types.computation()

Execute a command through the effect system.

The command will be passed to the installed handler function.

Example

Command.execute(%CreateTodo{title: "Buy milk"})

with_handler(comp, handler_fn)

Install a command handler for a computation.

The handler is a function (command -> computation) that receives the command and returns a computation. The computation can use any other effects installed in the pipeline.

Example

my_comp
|> Command.with_handler(&MyHandler.handle/1)
|> Comp.run!()

# Or with an anonymous function for dynamic routing:
my_comp
|> Command.with_handler(fn cmd ->
  handler = Map.fetch!(handlers, cmd.__struct__)
  handler.(cmd)
end)
|> Comp.run!()