beamologist

beamologist

Event Sourcing with CQRS is a technique for building applications that are based on an immutable log of events, which makes it ideal for building concurrent, distributed systems.

Though it is gaining popularity, the number of options for storing these events is limited and require specialized services like Kurrent (aka Greg’s EventStore) or AxonIQ.
One of the strong-points of the BEAM is, that it comes ‘batteries included’: there are BEAM-native libraries for many common tasks, like: storage, pub/sub, caching, logging, telemetry, etc.

ExESDB is an attempt to create a BEAM-native Event Store, building further upon the Khepri library, which in turn builds upon the Ra library.

On the roadmap:

  • integration with pg2 and Phoenix.PubSub for side effects (i.e. read model projections)
  • interfacing with the Commanded library
  • leverage Partisan for clustering

Check it out on Hex or GitHub:

https://github.com/beam-campus/ex-esdb

Showing Posts 1 to 10

Eiji

Eiji

Interesting idea. I’m curious about plans for the commanded support.

So you plan to create an implementation for the Commanded.EventStore.Adapter behaviour, right? In that case it would be interesting to hear about a key differences between your library and PostgreSQL-based Elixir EventStore / EventStoreDB.

I guess it would be something like In memory event store, but for production. That should give us less required environment dependencies which is great. Are there any other pros for that like speed or security?

What kind of serializer would be needed? Would it work with the Elixir structs as-is or we would still need to use a JSON serializer?

Suppose some project already uses other adapter. Would that require some extra steps for migrating data?

beamologist

beamologist OP

Hi Tomasz,
Thank you for your feedback.
Next to the advantages you already mentioned (speed, security, no need for extra serialization - events are indeed stored as Erlang terms), I’d like to add the capability to deploy event sourced services as a self-contained BEAM-native release to the edge. This would allow us to leverage for instance The Nerves Project for deployment.
I am also looking in to https://bondy.io for scenarios where you could have 10E+N nodes in the network.
Much of my past work revolved around decentralized and autonomous systems (think Parking Facilities, Vehicles, Agricultural automation, Logistics etc), often in a “spotty” environment, where nodes aren’t always connected. Such systems benefit little from SaaS solutions, if the network is not available. That space could be considered my main motivator to build a BEAM-native event store: as few dependencies on 3rd party services as possible.

The reason for implementing the Commanded Adapter is simple: it is the de-facto event sourcing standard for the BEAM and is as far as I am concerned, feature complete.

When it comes to migrating data from existing stores, I’d argue that’s quite easy, barely an inconvenience: replay the old store and project into the new.
So, indeed: highest points on the agenda are:

1, have Kherpi triggers throw seen events on pg2 (for projections etc…)
2. Dynamic Clustering via Partisan
3. Commanded Adapter
4. Monitoring/Telemetry

garrison

garrison

This seems cool - love seeing more database projects in Elixir!

A couple of random questions from someone who knows very little about CQRS/ES:

Khepri, like Mnesia, is an in-memory database (which also persists to disk). If you’re storing an immutable log, would you eventually run out of memory? Or is the log truncated at some point?

Khepri, as I understand it, is a K/V store built on top of a Raft log. Since the thing you’re storing is, of course, a log, would it make more sense to use Ra directly?

I see you mentioned a large number of nodes. Is the idea here to have many individual Khepri clusters running independently within a large cluster?

What is Khepri’s throughput like? I would imagine you would get better results with aggressive batching.

beamologist

beamologist OP

Thank you for your input, those are some very valid points and concerns.
The main driver for this project is decentralization and in such scenarios, I’d imagine JIT availability and localized sharding functions as a counterweight to throughput. For now, I don’t worry about this too much yet and focus on getting the store operational.
Most of the dedicated Event Stores (I know of) are centralized at the data center level and there is not much literature about decentralized event sourcing. It probably opens a whole different can of worms, but we need tooling to investigate it. ExESDB should be seen in this context.

As an example, imagine the scenario of a parking facility where vehicles enter and exit, people enter and exit, payments are made etc…next, imagine such a facility not being managed by a centralized system, but rather by a mesh of SBCs that perform individual parts of the process. Such a system might consist of a few hundred devices, and indeed, in that mesh there might be a number of individual realms that are responsible for parts of the process.

byu

byu

I will definitely follow your progress on this, sounds interesting.

Question:

If the assumption is to run this “at scale”, whatever that may be, what is the concept/approach about consistency boundaries for said scale?

That is, in EventStoreDB (Kurrent) and Commanded’s own Postgres EventStore, there is the “stream local” boundary with optimistic concurrency for the stream itself-- aka the incrementing gapless version number between events in a stream–, but these events do get projected into some order in the $all stream.

  1. Is the use of khepri and ra to make sure that the “individual stream” is consistent across the distributed cluster nodes?
  2. And that also there will be an $all stream (or other projections) that also will provide some sort of consistent ordering across the cluster? Also using khepri and ra?

Given that Kurrent has an HA cluster solution, I’m assuming that there is known distributed systems approach to merge all these various distributed small stream events into a combined single $all projection? If so, what is it? Got references for me to learn from? And how would ExESDB accomplish this task?

Thanks for the experimenting of your project and edifying me on this.

beamologist

beamologist OP

Hi Byu,
Thank you for your interest and comment and sorry for the belated reply.
To answer some of your questions:
The mechanism that is used for emitting events from the store, relies on Khepri’s built-in triggering capabilities: when a node in a Khepri path is created, a ‘stored function’ can be activated, which emits the corresponding event, if path and payload satisfy certain filter conditions. However, this capability is only available on Ra leader nodes, so a Follow-the- Leader mechanism is implemented to transfer the Emitter subsystem to the new Leader upon election.

Since v0.0.15, ExESDB supports

  • For ‘transient subscriptions’
    3 flavors: :by_stream ($all or $stream_id), :by_event_type and :by_event_payload.
  • For ‘persistent subscriptions’
    only :by_stream has practical relevance, as far as I know
  • ExESDB.GatewayAPI
    Using the swarm library, a Gateway is implemented, which routes requests to a random available node in an ExESDB cluster, thus achieving some Load-Balancing and High-Availability.

Tests and Experimentation so far show quite good results in terms of consistency and event ordering, even when performing chaos testing on the cluster (I must admit, to my slight surprise) which is testament to the excellent work done by the giants on whose shoulders we stand :slight_smile:

I did create a little demo clip (sorry for the terrible audio, conditions are sub-optimal for now)

beamologist

beamologist OP

ExESDB v0.1.0 available!
I am proud to announce that the first useful release of ExESDB is now available as v0.1.0! This release comes with an adapter for the fantastic Commanded Library AND a Phoenix LiveView demo app. Feel free to check it out

On Hex:

On Github

DEMO Video
Comments and Feedback most welcome!

10
Post #7
beamologist

beamologist OP

Hi Eiji,

It has taken me a few months to finish things up (but then, what is ‘finished’, right?) but meanwhile, the distributed store is there, a HA proxy is there and…the Commanded adapter is there, too!
It is said that the proof of the pudding is in the eating, so the adapter is being developed and tested in conjunction with a working Phoenix LiveView application: an event-sourced demo app that mimics a dashboard for regulating greenhouses. All data (events) is stored in ExESDB, while Cachex is used for read models, thus creating a true BEAM-only application without the need of any external services like EventStoreDB or PostgreSQL.

I must confess, it feels a little liberating, being able to just spin up a few containers and not having to worry about connectivity with other backend components.

Also, since we remain in the same ecosystem, there is no need to worry about (or waste processing power with) serialization. Serialization will only become a topic if and when we decide to create API’s for clients in other languages..

AndyX

AndyX

wow!!! that is unbelievable news!! i recently started exploring commanded library, and having now native eventstore is amazing news! what’s your plans for future releases?

byu

byu

Congrats on your effort. I can’t wait to give this a spin on my next weekend project!

Where Next? Top

Trending in Announcing Top

wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
restlessronin
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub. Docs are at OpenaiEx User Gu...
152 11030 135
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
fuelen
Hi all! I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas. You...
New
woylie
Phoenix components for pagination, sortable tables and filter forms with Flop and (optionally) Ecto. pagination cursor pagination sorta...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews