Event Sourcing with SQL Stream Store

Event Sourcing with SQL Stream Store

I’ve known about SQL Stream Store for a bit (I believe when it was called Cedar) but haven’t really looked into it much. The premise is to provide a stream store over SQL. Currently supporting MS SQL Server, PostgreSQL, and MySQL. Meaning it is simply a .NET Library you can use with an SQL implementation. Let’s take a look at how you can implement Event Sourcing with SQL Stream Store.

SQL Stream Store Demo Application

For this demo/sample, I’m going to create a .NET Core 3 console app. The idea will be to create the stereotypical event-sourcing example of a bank account.

I wanted to explore the primary functions needed of an event stream.

  • Create a Stream
  • Append a new Event to a Stream
  • Read Events from a Stream
  • Subscribe to a Stream to receive appended Events

NuGet Package

As always, the first thing is to get the SqlStreamStore NuGet Package by adding it as a PackageReference in your csproj.

I’ve also included Newtonsoft.Json because I’m going to be (de)serializing events.

Events

I’m going to create two events to represent the bank account transactions. Deposited and Withdrawn. Both of these will extend the abstract AccountEvent that will contain the TransactionId, Dollar Amount, and DateTime of the event.

Creating a Stream

There is no way of creating an empty stream. This is actually really nice. Instead when appending an event to a stream, if the stream does not already exist, it’s created. This is the same how EventStore works and should also feel familiar in comparison to the API.

Appending to a Stream

Appending a new event to a stream is pretty straight forward. From the IStreamStore there is an AppendToStream method that takes a few args.

The first is StreamId. This generally would represent your aggregate root ID. In this demo, I’m setting it Account:{GUID}.

The second arg is ExpectedVersion. This is also similar to the EventStore API. This is used for handling concurrency. You can specify an integer that represents the number of events that are persisted in the stream. You can also use the ExpectedVersion enum that can specify Any to not concern yourself with concurrency or NoStream to verify its the first event.

Finally, the 3rd param is an instance of NewStreamMessage. It contains the MessageId (GUID), an event name and the event json body.

An interesting takeaway here is the event name is intentionally made as a string so you are not serializing/deserializing to the CRL type name. This is a great idea since the CLR type name is likely to be changed more than just a plain string which you can keep constant.

Reading a Stream

You can read a stream forward or backward. Forward meaning from the very first event until the last, which is what I’ll use in this example.

You simply specify the StreamId, the starting version (0) and how many events to pull from the stream. The result contains an IsEnd to indicate there are no more events left in the stream to read.

Subscribing to a Stream

Subscribing to a stream is pretty straight forward. Specify the StreamId, the starting version/position of where you want to be notified of new events from, and then StreamMessageReceived for handling the newly appended event.

Wrapping it up

Now that I’ve covered all the primary aspects, it’s just a matter of adding some input/output to our console app by allowing the user to deposit and withdrawal from the account.

In the demo, I’m using the InMemoryStreamStore so there is no persisted data upon restarting the app. I’m also using a new GUID to represent the AccountId on each run.

Source Code

All the source code shown in this post is available on GitHub.

This was a quick look at just a few of the APIs in SQL Stream Store but should give you a feel for how it works.

If you’d like a more detailed contented related to various aspects of event sourcing, let me know in the comments or on twitter.

https://github.com/dcomartin/SqlStreamStore.Demo

Related Links:

Follow @CodeOpinion on Twitter

Software Architecture & Design

Get all my latest YouTube Vidoes and Blog Posts on Software Architecture & Design

EventStore for Orleans Grain Persistence

EventStore for Orleans Grain PersistenceIn my previous post, I used the JournaledGrain to create an Event Sourced grain.  This enabled us to raise events from within our grain which would be applied to our grain state.  Next up, which I’m covering in this post is how to use EventStore for Orleans Grain Persistence. This means when we raise events, they will also be persisted to EventStore.  When our grain is activated, we can re-hydrate it by retrieving prior events from an EventStore stream and re-running them in our Grain to get back to current state.

Blog Post Series:

EventStore

If you are unfamiliar with EventStore:
The open-source, functional database with Complex Event Processing in JavaScript.
If you don’t have a running instance, the easiest way is probably with Docker.  Pull down the latest image from docker hub and  as single node running. docker pull eventstore/eventstore docker run –name eventstore-node -it -p 2113:2113 -p 1113:1113 eventstore/eventstore There is a .NETStandard 2.0 compatible client package that I will be using in our Grain Project. Install-Package EventStore.ClientAPI.NetCore

Writing to EventStore

Anytime our grain was calling the JournaledGrain.RaiseEvent, we want to actually persist that to an EventStore Stream.  For my demo, we will have one EventStore stream per instance of an Orleans grain.  Meaning each bank account will have one event stream. I’m going to create a new RaiseEvent method that will call the base.RaiseEvent and once confirmed they were applied, append them to our EventStore Stream.  The additional private static methods are really just helpers for (de)serializing our events from/to json.

Re-hydrating

When our Grain activates with OnActivateAsync, this is when we will fetch all the events from our event stream and apply them to our grain.  Basically this will be replaying all the events to build our grain state back up to current state.
 

More!

If you want to try the demo, all the source is available on my PracticalOrleans GitHub Repo. Do you have any questions or comments? Are you using Orleans or EventStore?  I’d love to hear about it in the comments or on Twitter.
Follow @CodeOpinion on Twitter

Software Architecture & Design

Get all my latest YouTube Vidoes and Blog Posts on Software Architecture & Design

Practical Microsoft Orleans

I’ve been wanting to take a deeper dive into Microsoft Orleans for awhile now.  With the next release targeting .NET Standard 2.0, it felt like an great time to do it.  This is the first blog post in a series that will go beyond a simple Hello World.  The plan is to make this a practical Microsoft Orleans guide to follow along with.

Blog Post Series:

Microsoft Orleans

If you aren’t familiar with Orleans, here’s a brief overview.

Orleans is a framework that provides a straightforward approach to building distributed high-scale computing applications, without the need to learn and apply complex concurrency or other scaling patterns.

Or maybe you have heard Orleans is an Actor model framework.  Well…

Implementation of Orleans is based on the Actor Model that’s been around since 1970s. However, unlike actors in more traditional actor systems such as Erlang or Akka, Orleans Grains are virtual actors. The biggest difference is that physical instantiations of grains are completely abstracted away and are automatically managed by the Orleans runtime. The Virtual Actor Model is much more suitable for high-scale dynamic workloads like cloud services and is the major innovation of Orleans. You can read more details in the Technical Report on Orleans.

Docs

I have to give it to the Orleans team.  Their docs seem fantastic.  I’ve read over most of their Step-by-Step guide and feel like there’s a lot of insight being shared.  There’s a section about Concurrency that has some great code samples that gives with code samples a deadlock scenario.  I found reading over these docs to be really helpful in understanding and just looking at small code samples.

Event Sourcing

One aspect that I find interesting is having a grain manage it’s state being event sourced.

Event sourcing provides a flexible way to manage and persist grain state. An event-sourced grain has many potential advantages over a standard grain. For one, it can be used with many different storage provider configurations, and supports geo-replication across multiple clusters. Moreover, it cleanly separates the grain class from definitions of the grain state (represented by a grain state object) and grain updates (represented by event objects).

My plan is to use event sourcing as grain state and persist events to Event Store.  Luckily I’m familiar enough with Event Store however have to do more reading on if there is an existing implementation or have to roll my own.

Sample Application

As with other blog series I’ve done in the past, I find it helpful to take an existing OSS application that I can fork and use as a base.

Do you have a suggestion about an application I can fork to use as a base?  I’d love to hear your suggestions.  Let me know Twitter or in the comments.

Follow @CodeOpinion on Twitter