Build Status Hex version Coverage Status

Building blocks for distributed and/or CQRS/ES systems in Elixir.

X3m.System gives you a small set of composable pieces for building message-driven backends: a message that carries a request and its response, a router that registers services across a cluster, a dispatcher that finds a node offering a service and waits for the reply, and — when you need it — aggregates with event sourcing and a backend-agnostic scheduler for delivering messages in the future.

The pieces are à la carte. You can use the messaging layer (message + router + dispatcher) on its own, add aggregates and event sourcing only where you need them, and use the scheduler independently of everything else.

Installation

def deps do
  [
    {:x3m_system, "~> 0.9.1"}
  ]
end

One dependency is optional:

  • :elixir_uuid — needed when working with aggregates (id generation).

A minimal example

Define a router that registers a service and the module that handles it:

defmodule MyApp.Router do
  use X3m.System.Router

  service :greet, MyApp.Greeter

  def authorize(_message), do: :ok
end

defmodule MyApp.Greeter do
  alias X3m.System.Message

  def greet(%Message{} = message) do
    name = message.raw_request["name"]
    {:reply, Message.ok(message, "Hello, #{name}!")}
  end
end

Register the services (typically from your application's start/2) and dispatch a message to the service by name:

:ok = MyApp.Router.register_services()

:greet
|> X3m.System.Message.new(raw_request: %{"name" => "Ada"})
|> X3m.System.Dispatcher.dispatch()
#=> %X3m.System.Message{response: {:ok, "Hello, Ada!"}, ...}
flowchart LR
  C[Caller] -->|"Message.new(:greet)"| D[Dispatcher.dispatch]
  D -->|find a node offering :greet| R[Router]
  R -->|"authorize/1"| A{authorized?}
  A -->|no| F["response: {:error, :forbidden}"]
  A -->|yes| H["Greeter.greet/1"]
  H -->|"{:reply, Message.ok(...)}"| C

No aggregates or event store are involved here — any module registered through a router can be a dispatch target.

Guides

  • Getting started — install, optional deps, your first dispatch.
  • MessagingMessage, Router, Dispatcher and the response shapes.
  • Aggregates & event sourcingAggregate, MessageHandler, persisting events, snapshotting and supervision.
  • Distribution — service discovery across nodes, choosing the node, and forwarding.
  • Scheduling — persistable, future-dated message delivery with Scheduler.

License

Released under the MIT License. See the LICENSE file.