Skip to content

small DB engine specifically for Event Sourcing, written in .NET

License

Notifications You must be signed in to change notification settings

mizrael/EvenireDB

Repository files navigation

EvenireDB

Tests

Evenire, from Latin, present active infinitive of ēveniō, "to happen".

This project is a Proof-of-Concept of a small DB engine specifically for Event Sourcing. If you don't know what Event Sourcing is, I've been writing for a while about it on my blog. These articles can be a good starting point:

I took a personal interest in this amazing pattern and after a while using it, I also wanted to write a database system specifically suited for it. Honestly, I don't know how far this project will go, but I'm having a lot of fun so far and I am definitely learning a lot :)

How does it work?

The basic idea behind Evenire is quite simple: events can be appended to stream and later on, retrieved by providing the stream ID.

Every stream is kept in memory using a local cache, for fast retrieval. A background process takes care of serializing events to a file, one per stream.

Reading can happen from the very beginning of a stream moving forward or from a specific point. This is the basic scenario, useful when you want to rehydrate the state of an Aggregate.

Another option is to read the events from the end of the stream instead, moving backwards in time. This is interesting for example if you are recording data from sensors and you want to retrieve the latest state.

Setup

As of now, there are two possible options for spinning up an Evenire server:

These are both viable options, however, I would recommend opting for the Docker solution as it will package everything you need in the container. Building the image can be done using this script.

Once you have the image ready, you can run it in a Container by running docker compose up.

Client configuration

Once your server is up, you can start using it to store your events. If you are writing a .NET application, you can leverage the Client library I provided.

Configuration is pretty easy, just add this to your Program.cs or Startup.cs file:

var builder = WebApplication.CreateBuilder(args);

var connectionString = new Uri(builder.Configuration.GetConnectionString("evenire"));

builder.Services.AddEvenireDB(new EvenireConfig(connectionString, useGrpc: true));

Writing events

Once you have added the Client to your IoC Container, just inject IEventsClient into your classes and start making calls to it:

var streamId = Guid.NewGuid();

await _eventsClient.AppendAsync(streamId, new[]
{
    Event.Create(new{ Foo = "bar" }, "Event type 1"),
    Event.Create(new{ Bar = "Baz" }, "Event type 1"),
});

Reading events

Reading too can be done trough an IEventsClient instance:

var streamId = Guid.NewGuid();

// write some events for streamId...

await foreach(var @event in client.ReadAsync(streamId, StreamPosition.Start, Direction.Forward).ConfigureAwait(false)){
  // do something with the event
}

ReadAsync can be configured to fetch the events from StreamPosition.Start, StreamPosition.End or a specific point in the stream. You can also specify the direction you want to move (forward or backward).

Samples

  • TemperatureSensors shows how to use a Background worker to produce events and uses Minimal APIs to retrieve the latest events for a specific stream.

TODO

  • snapshots
  • backup and replicas
  • cluster management

About

small DB engine specifically for Event Sourcing, written in .NET

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project