CQRS event store implemented in Elixir. Uses PostgreSQL (v9.5 or later) as the underlying storage engine.
EventStore supports running on a cluster of nodes (since v0.11). Stream processes will be distributed amongst all available nodes, events are published to subscribers running on any node.
MIT License
- Getting started
- Using the EventStore
- Running on a cluster
- Event serialization
- Upgrading an EventStore
- Used in production?
- Backup and administration
- Benchmarking performance
- Contributing
- Need help?
Append events to a stream:
stream_uuid = UUID.uuid4()
expected_version = 0
events = [
%EventStore.EventData{
event_type: "Elixir.ExampleEvent",
data: %ExampleEvent{key: "value"},
metadata: %{user: "someuser@example.com"},
}
]
:ok = EventStore.append_to_stream(stream_uuid, expected_version, events)
Read all events from a single stream, starting at the stream's first event:
{:ok, events} = EventStore.read_stream_forward(stream_uuid)
More: Using the EventStore
Subscribe to events appended to all streams:
{:ok, subscription} = EventStore.subscribe_to_all_streams("example_subscription", self())
receive do
{:events, events} ->
# ... process events & ack receipt
EventStore.ack(subscription, events)
end
More: Subscribe to streams
Yes, this event store is being used in production.
PostgreSQL is used for the underlying storage. Providing guarantees to store data securely. It is ACID-compliant and transactional. PostgreSQL has a proven architecture. A strong reputation for reliability, data integrity, and correctness.
You can use any standard PostgreSQL tool to manage the event store data:
Run the benchmark suite using mix with the bench
environment, as configured in config/bench.exs
. Logging is disabled for benchmarking.
$ MIX_ENV=bench mix do es.reset, app.start, bench
Example output:
## AppendEventsBench
append events, single writer 100 10170.26 µs/op
append events, 10 concurrent writers 20 85438.80 µs/op
append events, 100 concurrent writers 2 1102006.00 µs/op
## ReadEventsBench
read events, single reader 1000 1578.10 µs/op
read events, 10 concurrent readers 100 16799.80 µs/op
read events, 100 concurrent readers 10 167397.30 µs/op
Pull requests to contribute new or improved features, and extend documentation are most welcome.
Please follow the existing coding conventions, or refer to the Elixir style guide.
You should include unit tests to cover any changes.
Please open an issue if you encounter a problem, or need assistance.
For commercial support, and consultancy, please contact Ben Smith.