Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
lib
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Maestro

Maestro is an event sourcing library. It is inspired by CQRS and re-uses terminology where appropriate. The divergence from being a CQRS framework is intentional as Maestro focuses on processing commands in a consistent manner and replaying events in a consistent order.

Currently, the only storage adapter suited to a multi-node environment is the Maestro.Store.Postgres adapter. The Maestro.Store.InMemory adapter exists for testing purposes only.

Status

Hex Build Status Coverage

Documentation is available here.

Installation

def deps do
  [{:maestro, "~> 0.2"}]
end

Database Configuration

Maestro is intended to be used alongside an existing database/ecto repo.

config :maestro,
  storage_adapter: Maestro.Store.Postgres,
  repo: MyApp.Repo

To generate the migrations for the snapshot and event logs, do:

mix maestro.create.event_store_migration

Example

There are three behaviours that make the command/event lifecycle flow: Maestro.Aggregate.CommandHandler, Maestro.Aggregate.EventHandler, and Maestro.Aggregate.ProjectionHandler. Modules implementing the command and event handler behaviours are looked up via a configurable :command_prefix and :event_prefix respectively. Projections are reserved for maintaining other models/representations within the event's transaction.

defmodule MyApp.Aggregate do
  use Maestro.Aggregate.Root,
    command_prefix: MyApp.Aggregate.Commands,
    event_prefix: MyApp.Aggregate.Events

  def initial_state, do: %{"value" => 0}

  def prepare_snapshot(state), do: state

  def use_snapshot(_curr, %Maestro.Types.Snapshot{body: state}), do: state
end

defmodule MyApp.Aggregate.Commands.IncrementCounter do

  @behaviour Maestro.Aggregate.CommandHandler

  alias Maestro.Types.Event

  def eval(aggregate, _command) do
    [
      %Event{
        aggregate_id: aggregate.id,
        type: "counter_incremented",
        body: %{}
      }
    ]
  end
end

defmodule MyApp.Aggregate.Events.CounterIncremented do

  @behaviour Maestro.Aggregate.EventHandler

  def apply(state, _event), do: Map.update!(state, "value", &(&1 + 1))
end
iex(1)> {:ok, id} = MyApp.Aggregate.new()
iex(2)> :ok = MyApp.Aggregate.evaluate(%Maestro.Types.Command{aggregate_id: id, type: "increment_counter", data: %{}})
iex(3)> {:ok, %{"value" => 1}} = MyApp.Aggregate.get(id)

About

an event store + cqrs

Resources

License

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages