Giter VIP home page Giter VIP logo

eventsourcing.netcore's Introduction

Build status Docker Build Status Financial Contributors on Open Collective

EventSourcing.NetCore

Example of Event Sourcing in .NET Core

Prerequisites

For running the Event Store examples you need to have Postgres DB. You can get it by:

  • Installing Docker, going to the docker folder and running:
docker-compose up

More information about using .NET Core, WebApi and Docker you can find in my other tutorial: .Net Core With Docker

Video presentation (PL):

Video presentation (PL)

Slides (PL):

Libraries used

  1. Marten - Event Store

  2. MediatR - Message Bus (for processing Commands, Queries, Events)

Suggested Order of reading

1. Event Store - Marten

  • Creating event store
  • Event Stream - is a representation of the entity in event sourcing. It's a set of events that hapened for the entity with the exact id. Stream id should be unique, can have different types but usually is a Guid.
    • Stream starting - stream should be always started with a unique id. Marten provides three ways of starting stream:
      • calling StartStream method with a stream id
        var streamId = Guid.NewGuid();
        documentSession.Events.StartStream<TaskList>(streamId);
      • calling StartStream method with a set of events
        var @event = new TaskCreated { TaskId = Guid.NewGuid(), Description = "Description" };
        var streamId = documentSession.Events.StartStream<TaskList>(@event);
      • just appending events with a stream id
        var @event = new TaskCreated { TaskId = Guid.NewGuid(), Description = "Description" };
        var streamId = Guid.NewGuid();
        documentSession.Events.Append(streamId, @event);
    • Stream loading - all events that were placed on the event store should be possible to load them back. Marten allows to:
      • get list of event by calling FetchStream method with a stream id
        var eventsList = documentSession.Events.FetchStream(streamId);
      • geting one event by its id
        var @event = documentSession.Events.Load<TaskCreated>(eventId);
    • Stream loading from exact state - all events that were placed on the event store should be possible to load them back. Marten allows to get stream from exact state by:
      • timestamp (has to be in UTC)
        var dateTime = new DateTime(2017, 1, 11);
        var events = documentSession.Events.FetchStream(streamId, timestamp: dateTime);
      • version number
        var versionNumber = 3;
        var events = documentSession.Events.FetchStream(streamId, version: versionNumber);
  • Event stream aggregation - events that were stored can be aggregated to form the entity once again. During aggregation process events are taken by the stream id and then replied event by event (so eg. NewTaskAdded, DescriptionOfTaskChanged, TaskRemoved). At first empty entity instance is being created (by calling default constructor). Then events based of the order of apperance (timestamp) are being applied on the entity instance by calling proper Apply methods.
    • Aggregation general rules
    • Online Aggregation - online aggregation is a process when entity instance is being constructed on the fly from events. Events are taken from the database and then aggregation is being done. The biggest advantage of the online aggregation is that it always gets the most recent business logic. So after the change it's automatically reflected and it's not needed to do any migration or updates.
    • Inline Aggregation (Snapshot) - inline aggregation happens when we take the snapshot of the entity from the db. In that case it's not needed to get all events. Marten stores the snapshot as a document. This is good for the performance reasons, because only one record is being materialized. The con of using inline aggregation is that after business logic has changed records need to be reaggregated.
    • Reaggregation - one of the biggest advantage of the event sourcing is flexibility to business logic updates. It's not needed to perform complex migration. For online aggregation it's not needed to perform reaggregation - it's being made always automatically. Inline aggregation needs to be reaggregated. It can be done by performing online aggregation on all stream events and storing the result as a snapshot.
      • reaggregation of inline snapshot with Marten
        var onlineAggregation = documentSession.Events.AggregateStream<TEntity>(streamId);
        documentSession.Store<TEntity>(onlineAggregation);
        documentSession.SaveChanges();
  • Event transformations
  • Events projection

2. Message Bus (for processing Commands, Queries, Events) - MediatR

  • Initialization - MediatR uses services locator pattern to find proper handler for message type.
  • Sending Messages - finds and uses first registered handler for the message type. It could be used for queries (when we need to return values), commands (when we performing an action).
    • No Handlers - when MediatR doesn't find proper handler it throws an exception.
    • Single Handler - by implementing implementing IRequestHandler we're making decision that this handler should be run asynchronously with other async handlers (so we don't wait for the previous handler to finish its work).
    • More Than One Handler - when there is more than one handler registered MediatR takes only one ignoring others when Send method is being called.
  • Publishing Messages - finds and uses all registered handlers for the message type. It's good for processing events.
    • No Handlers - when MediatR doesn't find proper handler it throws an exception
    • Single Handler - by implementing implementing INotificationHandler we're making decision that this handler should be run asynchronously with other async handlers (so we don't wait for the previous handler to finish its work)
    • More Than One Handler - when there is more than one handler registered MediatR takes only all of them when calling Publish method
  • Pipeline (to be defined)

3. CQRS (Command Query Responsibility Separation)

4. Fully working sample application

See also fully working sample application in Sample Project

  • See sample how Entity Framework and Marten can coexist together with CQRS and Event Sourcing

5. Self-paced training Kit

I prepared self-paced training Kit for the Event Sourcing. See more in the Workshop description.

It's splitted into two parts:

Event Sourcing basics - it teaches the event store basics by showing how to build your own Event Store on Relational Database. It starts with the tables setup, goes through appending events, aggregations, projectsions, snapshots and finishes with the Marten basics. See more in here.

  1. Streams Table
  2. Events Table
  3. Appending Events
  4. Optimistic Concurrency Handling
  5. Event Store Methods
  6. Stream Aggregation
  7. Time Travelling
  8. Aggregate and Repositories
  9. Snapshots
  10. Projections
  11. Projections With Marten

Event Sourcing advanced topics - it's a real world sample of the microservices written in Event-Driven design. It explains the topics of modularity, eventual consistency. Shows practical usage of WebApi, Marten as Event Store, Kafka as Event bus and ElasticSearch as one of the read stores. See more in here.

  1. Meetings Management Module - module responsible for creating, updating meetings details. Written in Marten in Event Sourcing pattern. Provides both write model (with Event Sourced aggregates) and read model with projections.
  2. Meetings Search Module - responsible for searching and advanced filtering. Uses ElasticSearch as a storage (because of it's advanced searching capabilities). It's a read module that's listening for the events published by Meetings Management Module.

6. Nuget packages to help you get started.

I gathered and generalized all of practices used in this tutorial/samples in Nuget Packages of maintained by me GoldenEye Framework. See more in:

  • GoldenEye DDD package - it provides set of base and bootstrap classes that helps you to reduce boilerplate code and help you focus on writing business code. You can find all classes like Commands/Queries/Event handlers and many more. To use it run:

    dotnet add package GoldenEye.Backend.Core.DDD

  • GoldenEye Marten package - contains helpers, and abstractions to use Marten as document/event store. Gives you abstractions like repositories etc. To use it run:

    dotnet add package GoldenEye.Backend.Core.Marten

The simplest way to start is installing the project template by running

dotnet new -i GoldenEye.WebApi.Template.SimpleDDD

and then creating new project based on it:

dotnet new SimpleDDD -n NameOfYourProject

7. Other resources

I found an issue or I have a change request

Feel free to create an issue on GitHub. Contributions, pull requests are more than welcome!

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

EventSourcing.NetCore is Copyright © 2017-2019 Oskar Dudycz and other contributors under the MIT license.

eventsourcing.netcore's People

Contributors

dennisdoomen avatar lukasz-pyrzyk avatar monkeywithacupcake avatar mrnustik avatar oskardudycz avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.