{"id":16990361,"url":"https://github.com/mizrael/eveniredb","last_synced_at":"2025-03-17T09:30:36.010Z","repository":{"id":196134427,"uuid":"692273613","full_name":"mizrael/EvenireDB","owner":"mizrael","description":"small stream-based DB engine","archived":false,"fork":false,"pushed_at":"2024-10-15T13:43:59.000Z","size":1072,"stargazers_count":36,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-24T21:53:51.475Z","etag":null,"topics":["database","dotnet","event-sourcing","stream"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mizrael.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mizrael"}},"created_at":"2023-09-16T01:33:41.000Z","updated_at":"2024-10-15T13:44:00.000Z","dependencies_parsed_at":"2023-10-10T19:09:59.898Z","dependency_job_id":"99c1f093-1fc2-4a78-8177-5a0414b90200","html_url":"https://github.com/mizrael/EvenireDB","commit_stats":null,"previous_names":["mizrael/eveniredb"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizrael%2FEvenireDB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizrael%2FEvenireDB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizrael%2FEvenireDB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizrael%2FEvenireDB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mizrael","download_url":"https://codeload.github.com/mizrael/EvenireDB/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243858235,"owners_count":20359253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","dotnet","event-sourcing","stream"],"created_at":"2024-10-14T03:09:49.114Z","updated_at":"2025-03-17T09:30:35.208Z","avatar_url":"https://github.com/mizrael.png","language":"C#","funding_links":["https://github.com/sponsors/mizrael"],"categories":[],"sub_categories":[],"readme":"# EvenireDB\n\n[![Tests](https://github.com/mizrael/EvenireDB/actions/workflows/dotnet.yml/badge.svg)](https://github.com/mizrael/EvenireDB/actions/workflows/dotnet.yml)\n![coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/mizrael/ebd585c5ad0069d0e8486e43cade5793/raw/eveniredb-code-coverage.json)\n[![client Nuget](https://img.shields.io/nuget/v/EvenireDB.Client?style=plastic)](https://www.nuget.org/packages/EvenireDB.Client/)\n\n\u003e [Evenire](https://en.wiktionary.org/wiki/evenire), from Latin, present active infinitive of *ēveniō*, \"to happen\".\n\nThis project is a Proof-of-Concept of a small stream-based DB engine. \n\nOne of the potential use cases is Event Sourcing. If you don't know what Event Sourcing is, I've been writing for a while about it on [my blog](https://www.davidguida.net). These articles can be a good starting point:\n- [Event Sourcing in .NET Core – part 1: a gentle introduction](https://www.davidguida.net/event-sourcing-in-net-core-part-1-a-gentle-introduction/)\n- [Event Sourcing: 5 things to consider when approaching it](https://www.davidguida.net/event-sourcing-things-to-consider)\n\nI 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.\nHonestly, 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 :)\n\n## How does it work?\n\nThe basic idea behind Evenire is quite simple: events can be appended to streams and later on, retrieved by providing the stream ID.\n\nStreams are identified by a tuple composed of a `Guid` (the stream key) and a string (the stream type). For the curious, the sources are [here](https://github.com/mizrael/EvenireDB/tree/main/src/EvenireDB.Common/StreamId.cs)).\n\nEvery 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.\n\nReading 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](https://www.martinfowler.com/bliki/DDD_Aggregate.html).\n\nAnother option is to read the events from the _end_ of the stream instead, moving backward in time. This is interesting for example if you are recording data from sensors and you want to retrieve the latest state.\n\nAuthN/Z was **left out intentionally** as it would go outside the scope of the project (for now).\n\n## Setup\n\nAs of now, there are two possible options for spinning up an Evenire server:\n- deploying the [Server project](https://github.com/mizrael/EvenireDB/tree/main/src/EvenireDB.Server) somewhere\n- building the [docker image](https://github.com/mizrael/EvenireDB/blob/main/Dockerfile) and deploying it somewhere\n\nThese 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](https://github.com/mizrael/EvenireDB/blob/main/scripts/dockerize.ps1).\n\nOnce you have the image ready, you can run it in a Container by running `docker compose up`.\n\n## Client configuration\n\nOnce 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](https://github.com/mizrael/EvenireDB/tree/main/src/EvenireDB.Client) I provided.\n\nClient configuration is pretty easy. The first step is to update your `appsettings.json` file and add a new section:\n```json\n{\n  \"Evenire\": {\n    \"ServerUri\": \"[your server url here]\",\n    \"HttpSettings\": {\n      \"Port\": 80 \u003c---- make sure this is correct for you\n    },\n    \"GrpcSettings\": {\n      \"Port\": 5243 \u003c---- make sure this is correct for you\n    }\n  }\n}\n```\n\nOnce you have that, the last step is to register EvenireDB on your DI container. Something like this:\n\n```csharp\nvar builder = WebApplication.CreateBuilder(args);\n\nvar clientConfig = builder.Configuration.GetSection(\"Evenire\").Get\u003cEvenireClientConfig\u003e();\n\nbuilder.Services.AddEvenireDB(clientConfig);\n```\n\n### Writing events\n\nOnce you have added the Client to your DI Container, just inject `IEventsClient` into your classes and start making calls to it:\n\n```csharp\nvar streamKey = /* this is a GUID */;\nvar streamId = new StreamId(streamKey, \"MyStreamType\");\n\nawait _eventsClient.AppendAsync(streamId, new[]\n{\n    Event.Create(new{ Foo = \"bar\" }, \"Event type 1\"),\n    Event.Create(new{ Bar = \"Baz\" }, \"Event type 1\"),\n});\n```\n\n### Reading events\n\nReading too can be done trough an `IEventsClient` instance:\n\n```csharp\nvar streamKey = /* this is a GUID */;\nvar streamId = new StreamId(streamKey, \"MyStreamType\");\n\n// write some events for streamId...\n\nawait foreach(var @event in client.ReadAsync(streamId, StreamPosition.Start, Direction.Forward).ConfigureAwait(false)){\n  // do something with the event\n}\n```\n\n`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).\n\n## Admin UI\nEvenire also has a rudimentary administration UI, written with Blazor. It allows a few basic operations:\n- see the list of all the available streams\n- create a new stream\n- append events to an existing stream\n- delete a stream\n\n![streams archive](https://raw.githubusercontent.com/mizrael/EvenireDB/main/docs/assets/streams_archive.jpg)\n\n![stream details](https://raw.githubusercontent.com/mizrael/EvenireDB/main/docs/assets/stream_details.jpg)\n\n## Samples\n- [TemperatureSensors](https://github.com/mizrael/EvenireDB/tree/main/samples/EvenireDB.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.\n\n## TODO\n- snapshots\n- backup and replicas\n- cluster management\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizrael%2Feveniredb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmizrael%2Feveniredb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizrael%2Feveniredb/lists"}