Skip to content

A library to facilitate communication between CommandService and QueryService. The Idea is when any event occures in commandService, it should be persisted in QueryService in MongoDb, SqlServer, MySql and PostgreSQL

Notifications You must be signed in to change notification settings

younos1986/Core.EventStore

Repository files navigation

Core.EventStore

.NET Core

A library to facilitate communication between CommandService and QueryService. The Idea is when any event occures in commandService, it should be persisted in QueryService in MongoDb, SqlServer, MySql and PostgreSQL

  • CommandService only keeps events in EventStore
  • QueryService's Projectors will be triggered when any event is stored in EventStore by CommandService

Nuget

Features

  • Keep track of last event position
  • Idempotency
  • Define multiple projectors for one event

Dependencies

.NETStandard 2.1

Autofac (>= 5.1.2)

EventStore.Client (>= 5.0.6)

MediatR (>= 7.0.0)

Microsoft.Extensions.Configuration.Abstractions (>= 3.1.2)

MongoDB.Driver (>= 2.10.0)

How to use

In CommandService

using Autofac;
using Core.EventStore.Autofac;

namespace CommandService.IoCC.Modules
{
    public class EventStoreModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterEventStore(initializationConfiguration =>
            {
                initializationConfiguration.Username = "admin";
                initializationConfiguration.Password = "changeit";
                initializationConfiguration.DefaultPort = 1113;
                //initializationConfiguration.IsDockerized = true;
                //initializationConfiguration.DockerContainerName = "eventstore";

                initializationConfiguration.IsDockerized = false;
                initializationConfiguration.ConnectionUri = "127.0.0.1";
            });
        }
    }
}


In QueryService

using Autofac;
using Core.EventStore.Autofac;
using IntegrationEvents;
using QueryService.InvokerPipelines;

namespace QueryService.IoCC.Modules
{
        public class EventStoreModule : Module
        {
            protected override void Load(ContainerBuilder builder)
            {
                builder.RegisterEventStore(initializationConfiguration =>
                {
                    initializationConfiguration.Username = "admin";
                    initializationConfiguration.Password = "changeit";
                    initializationConfiguration.DefaultPort = 1113;

                    //initializationConfiguration.IsDockerized = true;
                    //initializationConfiguration.DockerContainerName = "eventstore";

                    initializationConfiguration.IsDockerized = false;
                    initializationConfiguration.ConnectionUri = "127.0.0.1";
                })
                    .SubscribeRead(subscriptionConfiguration =>
                    {
                        subscriptionConfiguration.AddEvent<CustomerCreated>(nameof(CustomerCreated));
                        subscriptionConfiguration.AddEvent<CustomerModified>(nameof(CustomerModified));
                    }, new CustomProjectorInvoker())
                    .KeepPositionInMongo(configuration =>
                        {
                            configuration.ConnectionString = "mongodb://127.0.0.1";
                            configuration.DatabaseName = "TestDB";
                        })
                    .KeepIdempotencyInMongo();
            }
        }
    }

And register projectors

And Register 
using Autofac;
using Core.EventStore.Contracts;
using IntegrationEvents;
using QueryService.Projectors;

namespace QueryService.IoCC.Modules
{
    public class ProjectorsModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<CustomerCreatedEventProjector>().As<IProjector<CustomerCreated>>();
            builder.RegisterType<CustomerInsertedEventProjector>().As<IProjector<CustomerCreated>>();
        }
    }
}

Then persist occured event in CommandService


using System;
using System.Threading;
using System.Threading.Tasks;
using CommandService.Commands;
using CommandService.Dtos;
using Core.EventStore.Dependencies;
using IntegrationEvents;
using MediatR;

namespace CommandService.CommandHandlers
{
    public class CreateCustomerCommandHandler : IRequestHandler<CreateCustomerCommand, CustomerDto>
    {
        readonly IEventStoreDbContext _eventStoreDbContext;

        public CreateCustomerCommandHandler(IEventStoreDbContext eventStoreDbContext)
        {
            _eventStoreDbContext = eventStoreDbContext;
        }

        public async Task<CustomerDto> Handle(CreateCustomerCommand cmd, CancellationToken cancellationToken)
        {
            var @event = new CustomerCreated(cmd.FirstName, cmd.LastName, DateTime.UtcNow);

            //do sth
            
            var res = new CustomerDto()
            {
                FirstName = cmd.FirstName,
                LastName = cmd.LastName,
            };

            await _eventStoreDbContext.AppendToStreamAsync(@event);
            return res;
        }
    }
}

Then Projectors in QueryService will be triggered

using Core.EventStore.Contracts;
using IntegrationEvents;
using System.Threading.Tasks;
using QueryService.MongoDbConfigs;

namespace QueryService.Projectors
{
    public class CustomerCreatedEventProjector : IProjector<CustomerCreated>
    {
        private IMongoDb _mongoDb; 
        public CustomerCreatedEventProjector(IMongoDb mongoDb)
        {
            _mongoDb = mongoDb;
        }
        
        public async Task HandleAsync(CustomerCreated integrationEvent)
        {
            await _mongoDb.InsertOneAsync(integrationEvent);
        }
    }
}

About

A library to facilitate communication between CommandService and QueryService. The Idea is when any event occures in commandService, it should be persisted in QueryService in MongoDb, SqlServer, MySql and PostgreSQL

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published