ServcoX.EventSauce
3.0.0
See the version list below for details.
dotnet add package ServcoX.EventSauce --version 3.0.0
NuGet\Install-Package ServcoX.EventSauce -Version 3.0.0
<PackageReference Include="ServcoX.EventSauce" Version="3.0.0" />
paket add ServcoX.EventSauce --version 3.0.0
#r "nuget: ServcoX.EventSauce, 3.0.0"
// Install ServcoX.EventSauce as a Cake Addin #addin nuget:?package=ServcoX.EventSauce&version=3.0.0 // Install ServcoX.EventSauce as a Cake Tool #tool nuget:?package=ServcoX.EventSauce&version=3.0.0
ServcoX.EventSauce
Event Sauce is the light-weight event sourcing library Servco uses internally to store our events in Azure Table Storage. Its for when you want to use event sourcing but your needs (or budget) aren't demanding enough to justify using Kafka.
It's performant a modest scale, and since it backs on Azure Table Storage it's cost is tiny compared to just about everything else. It's also simple, and allows you to build out event sourcing in a way that suits you.
Installation
Grab it from NuGet from dotnet add package ServcoX.EventSauce
or dotnet add package ServcoX.EventSauce.DependencyInjection
for DI support.
Basic usage
Define your events like this:
public readonly record struct CakeBaked;
public readonly record struct CakeIced(String Color);
public readonly record struct CakeCut(Int32 Slices);
Connect to your event store like this:
var eventStore = new EventStore(connectionString: "UseDevelopmentStorage=true;", containerName: "EventSauce", aggregateName: "CAKE");
Or if you're using Microsoft DI, then you can use this:
builder.Services.AddEventSauce(connectionString: "UseDevelopmentStorage=true;", containerName: "EventSauce", aggregateName: "CAKE");
Write events like this:
var aggregateId = Guid.NewGuid().ToString("N");
await store.WriteEvent(aggregateId, new CakeBaked());
await store.WriteEvent(aggregateId, new CakeIced("BLUE"));
await store.WriteEvent(aggregateId, new CakeCut(3));
And finally, read events back like here:
foreach (var slice in await store.ListSlices())
{
foreach (var evt in await store.ReadEvents(slice.Id))
{
Console.WriteLine($"{evt.Type}: {evt.Payload}");
}
}
Projections
Once you have events being stored, you can then go a step further and create projections based on them.
Create a projection like this:
public record Cake
{
public String Id { get; set; } = String.Empty;
public Int32 Slices { get; set; }
public String Color { get; set; } = String.Empty;
public DateTime LastUpdatedAt { get; set; }
}
When you're creating your store, define how to build the projection:
var cakeProjection = store.Project<Cake>(version: 1, builder => builder
.OnCreation((projection, id) => projection.Id = id)
.OnEvent<CakeIced>((projection, body, evt) => projection.Color = body.Color)
.OnEvent<CakeCut>((projection, body, evt) => projection.Slices += body.Slices)
.OnUnexpectedEvent((projection, evt) => Console.Error.WriteLine($"Unexpected event ${evt.Type} encountered")) // Called for any event that doesn't have a specific handler
.OnAnyEvent((projection, evt) => projection.LastUpdatedAt = evt.At) // Called for all events - expected and unexpected
.IndexField(nameof(Cake.Color))
);
Then simply read the projection like this:
var aggregate = await cakeProjection.Read(aggregateId);
Or query on a field that has been indexed (see .Index
above):
var aggregates = cakeProjection.Query(nameof(Cake.Color), "BLUE");
When you query a projection it will play out all events that have occured since the last query using the projection definition, rendering the latest projection. The projection is then persisted in the database so that on the next query it needs only project events that have occured since.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net7.0
- Azure.Data.Tables (>= 12.8.2)
- Azure.Storage.Blobs (>= 12.19.1)
- ServcoX.Rfc7515C (>= 1.2.0)
-
net8.0
- Azure.Data.Tables (>= 12.8.2)
- Azure.Storage.Blobs (>= 12.19.1)
- ServcoX.Rfc7515C (>= 1.2.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ServcoX.EventSauce:
Package | Downloads |
---|---|
ServcoX.EventSauce.DependencyInjection
Dependency injection wrapper for Event sauce |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
4.0.4 | 1,769 | 3/14/2024 |
4.0.3 | 192 | 3/14/2024 |
4.0.2 | 254 | 3/13/2024 |
4.0.1 | 152 | 3/12/2024 |
4.0.0 | 165 | 3/12/2024 |
3.2.1 | 245 | 3/7/2024 |
3.2.0 | 532 | 2/16/2024 |
3.1.7 | 1,125 | 1/12/2024 |
3.1.6 | 312 | 1/12/2024 |
3.1.5 | 301 | 1/12/2024 |
3.1.4 | 386 | 1/12/2024 |
3.1.3 | 334 | 1/12/2024 |
3.1.2 | 338 | 1/11/2024 |
3.1.1 | 328 | 1/11/2024 |
3.1.0 | 305 | 1/11/2024 |
3.0.1 | 339 | 1/11/2024 |
3.0.0 | 425 | 1/10/2024 |
2.4.10 | 410 | 1/10/2024 |
2.4.9 | 347 | 1/10/2024 |
2.4.8 | 372 | 1/10/2024 |
2.4.7 | 422 | 1/9/2024 |
2.4.6 | 563 | 1/2/2024 |
2.4.5 | 536 | 1/2/2024 |
2.4.4 | 411 | 1/2/2024 |
2.4.3 | 409 | 1/2/2024 |
2.4.2 | 465 | 12/28/2023 |
2.4.1 | 427 | 12/28/2023 |
2.4.0 | 384 | 12/28/2023 |
2.3.0 | 399 | 12/27/2023 |
2.2.0 | 394 | 12/27/2023 |
2.1.0 | 416 | 12/27/2023 |
2.0.0 | 383 | 12/27/2023 |
1.1.0 | 398 | 12/25/2023 |
1.0.0 | 379 | 12/22/2023 |