azure-cosmos-dotnet-repository icon indicating copy to clipboard operation
azure-cosmos-dotnet-repository copied to clipboard

Event sourcing Integration Testing with InMemoryRepository fails due to Problems with Dependency Injection

Open henrikkarstrom opened this issue 1 year ago • 2 comments

Describe the bug I have a ASP.NET project where I use the Event Sourcing functionality from this SDK. Now I want to use the InMemoryRepository for Integration Testing of my project. But I have identified several problems when I try to do this. But in this bug, I will only care about the two related to Dependency Injection of the InMemoryRepository in the DefaultEventStore constructor.

Problem 1 DefaultEventStore.Def.cs injects two repositories in the constructor IBatchRepository<TEventItem> and IReadOnlyRepository<TEventItem>.

Only IReadOnlyRepository<> is registered when calling builder.Services.AddInMemoryCosmosRepository();. This causes problems where DefaultRepository is used for writes and InMemoryRepository is used for reads in DefaultEventStore. This can easily be solved by adding : (to src/Microsoft.Azure.CosmosRepository/Extensions/ServiceCollectionExtensions.cs AddInMemoryCosmosRepository method )

.AddSingleton(typeof(IBatchRepository<>), typeof(InMemoryRepository<>))

Problem 2 The DI service will now create two different instances of InMemoryRepository when creating DefaultEventStore after we have applied the fix from Problem 1. This will again give problem that we cannot read what we write in the DefaultEventStore. This will directly generate problems related to the AtomicEvent Etag. The simplest way to fix this is to rewrite the constructor in src/Microsoft.Azure.CosmosEventSourcing/Stores/DefaultEventStore.Def.cs from

public DefaultEventStore(
    IBatchRepository<TEventItem> batchRepository,
    IReadOnlyRepository<TEventItem> readOnlyRepository)
{
    _batchRepository = batchRepository;
    _readOnlyRepository = readOnlyRepository;
}

to

public DefaultEventStore(
    IRepository<TEventItem> repository)
{
    _batchRepository = repository;
    _readOnlyRepository = repository;
}

Notes

With my proposal for fix Problem 2, the fix from Problem 1 will be in relevant in this case, but I think that should be fixed anyway. Related issue: #266

Environment summary SDK Version: latest main branch OS Version: Windows

Additional context Program.cs

builder.Services.AddCosmosEventSourcing(eventSourcingBuilder =>
{
    eventSourcingBuilder.AddCosmosRepository(options =>
    {
options.DatabaseId = "gateway-sample-db";
        options.ContainerBuilder
            .ConfigureEventItemStore<XEventItem>(
                "x-events", containerOptionsBuilder: options => { options.WithServerlessThroughput(); })
            .ConfigureProjectionStore<XReadItem>(
                containerName: "x-projections",
                partitionKey: "/tenantId",
                containerOptionsBuilder: options => { options.WithServerlessThroughput(); });
    });

    eventSourcingBuilder
        .AddEventItemProjection<XEventItem,
            ReadProjectionKey,
            XReadProjection>(
            options =>
            {
                options.ProcessorName = "x-read-projection-builder";

                options.InstanceName =  Environment.MachineName;
            });

    eventSourcingBuilder.AddDomainEventTypes(typeof(Program).Assembly);
});

builder.Services.RemoveCosmosRepositories();

builder.Services.AddInMemoryCosmosRepository();

henrikkarstrom avatar Jul 05 '22 21:07 henrikkarstrom

Hi @henrikkarstrom thanks for this issue we have this on our radar and there is a re-write going on behind the scenes of the in memory repository implementation to try and deal with this a lot better, cc @robertbennett1998

The PR is still in draft here I think if you wanted to take a look https://github.com/IEvangelist/azure-cosmos-dotnet-repository/pull/268

Sorry for the slow response I've been away the last few weeks.

mumby0168 avatar Jul 12 '22 09:07 mumby0168

Hey @mumby0168 thanks for the reply here. I'm nearly done writing the book, which means I should be able to start committing more time to this project. Happy to review the referenced PR when it's out of draft.

IEvangelist avatar Jul 20 '22 03:07 IEvangelist