ServcoX.EventSauce 2.4.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package ServcoX.EventSauce --version 2.4.0                
NuGet\Install-Package ServcoX.EventSauce -Version 2.4.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ServcoX.EventSauce" Version="2.4.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ServcoX.EventSauce --version 2.4.0                
#r "nuget: ServcoX.EventSauce, 2.4.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ServcoX.EventSauce as a Cake Addin
#addin nuget:?package=ServcoX.EventSauce&version=2.4.0

// Install ServcoX.EventSauce as a Cake Tool
#tool nuget:?package=ServcoX.EventSauce&version=2.4.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.

Basic usage

Define your events like this:

public readonly record struct BakedCake : IEventBody;
public readonly record struct IcedCake(String Color) : IEventBody;
public readonly record struct CutCake(Int32 Slices) : IEventBody;

Connect to your event store like this:

var eventStore = new EventStore("=== connection string goes here ===");

Create a stream and write events like this:

var streamType = "CAKE";
var streamId = Guid.NewGuid().ToString();
var userId = Guid.NewGuid().ToString();
await eventStore.CreateStream(streamId, streamType);
await eventStore.WriteEvents(streamId, new BakedCake(), userId);
await eventStore.WriteEvents(streamId, new IcedCake("BLUE"), userId);
await eventStore.WriteEvents(streamId, new CutCake(3), userId);

Get a list of streams you've already created like so:

foreach (var stream in eventStore.ListStreams(streamType)) Console.WriteLine(stream.Id);

And finally, read events back like here:

var minVersion = 0; // <== Can pick a greater version to only read new events
foreach (var evt in eventStore.ReadEvents(streamId, minVersion)) Console.WriteLine(evt.Version + ": " + evt.Body);

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; }
    public Int32 Slices { get; set; }
    public String Color { get; set; }
    public DateTime LastUpdatedAt { get; set; }
}

When you're creating your store, define how to build the projection:

var store = new EventStore(connectionString, cfg => cfg
    .RefreshProjectionsAfterWriting()
    .DefineProjection<Cake>(streamType: "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.CreatedAt) // Called for all events - expected and unexpected
        .Index(nameof(Cake.Color), projection => projection.Color)
    )
);

Then simply read the projection like this:

var projection = await store.ReadProjection<Cake>(streamId);

Or query on a field that has been indexed (see .Index above):

var projections = store.ListProjections<Cake>(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 Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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