aryzac-io / Intent.Modules.NET

Example modules for .NET
0 stars 0 forks source link

[Feature]: 5959961188 - CosmosDB Optimistic concurrency through e-tags #2

Open stephanjohnson opened 7 months ago

stephanjohnson commented 7 months ago

What is required?

Add a setting called something like "Use Optimistic Concurrency Default" which is by default set to "On".

Will probably need repositories / Unit of work to keep track of Etags per document Id so that when we save, we send it back over.

this is a option which can be passed into the Cosmos operations like update and delete. Simple change, should it be a setting or the default behaviour.

new ItemRequestOptions { IfMatchETag = entity._etag }

Database transactions and optimistic concurrency control in Azure Cosmos DB | Microsoft Learn

stephanjohnson commented 7 months ago

I am going to create a couple of new projects with the following settings

Type: Clean Architecture Turn off Entity Framework Turn on Cosmos DB

I will experiment with different solutions for implementing this feature and discuss with the team.

stephanjohnson commented 7 months ago

One project will explore applying the etag as part of the method call for the Cosmos DB library that we use. An early problem with this was that the optional parameter is only available on Update methods, and not the Delete methods.

Another project will explore applying the etag to the document object when projecting from the entity. Cosmos DB should honor the existence of the etag on the document as it is received.

stephanjohnson commented 7 months ago

Ran into an issue while testing the Intent Generated code with the etag dictionary.

When reading an item, it is added to the dictionary based on its Id, but if you read the same item twice, you get an error because an item with the same key has been added already.

var customerA = await _customerRepository.FindByIdAsync(id, cancellationToken);
if (customerA is null)
{
    throw new NotFoundException($"Could not find CustomerA '{id}'");
}
var customerB = await _customerRepository.FindByIdAsync(id, cancellationToken);
if (customerB is null)
{
    throw new NotFoundException($"Could not find CustomerB '{id}'");
}

customerA.Name = "CustomerA";
_customerRepository.Update(customerA);
await _customerRepository.UnitOfWork.SaveChangesAsync(cancellationToken);

customerB.Name = "CustomerB";
_customerRepository.Update(customerB);
await _customerRepository.UnitOfWork.SaveChangesAsync(cancellationToken);
stephanjohnson commented 7 months ago

I completed the change, committed to the repo, just have to test the resulting generated code, and turn on the setting in one of the test projects

stephanjohnson commented 7 months ago

Testing the output completed. Next step is to modify one of the test projects to use this mode, and get it ready for CI SF tests

stephanjohnson commented 7 months ago

hmmm, one small problem is that the default value for "Use Optimistic Concurrency Default" is "On". This means that I have to update the version of the Intent.CosmosDB in all of the CosmosDB test projects, and turn it off for all except one.

This might have an unseen impact on other test projects that use the module that I am unaware of as just yet, and as I do not have visibility into the AzureDevOps pipelines, I won't know if a build fails.

I am going to have to search all of the modules.config files and update those projects too.

stephanjohnson commented 7 months ago

This is going to include the following other projects

image

C:\dev\Intent.Modules.NET\Tests\AdvancedMappingCrud.Cosmos.Tests\modules.config C:\dev\Intent.Modules.NET\Tests\CleanArchitecture.OnlyModeledDomainEvents\modules.config C:\dev\Intent.Modules.NET\Tests\CleanArchitecture.SingleFiles\modules.config C:\dev\Intent.Modules.NET\Tests\MultipleDocumentStores\modules.config

stephanjohnson commented 7 months ago

The only remaining issue that I have is the Settings implementation itself. Currently it looks like this:

image

I would imagine, and prefer, to have the Use Optimistic Concurrency Default in the Document Database setting group. I could not figure out how to reference the module from the Intent.Modules.NET to theIntent.Modules projects without potentially breaking the build.

Maybe there will be some help in the PR tomorrow 😄

stephanjohnson commented 7 months ago

After some feedback on the PR:

stephanjohnson commented 7 months ago

So the integration testing has opened a bit of a can of worms.

I had to upgrade the Microsoft.Extensions.Http nuget package version in the Intent.Modules.Integration.HttpClients.Shared shared code project, and update all of the version numbers and release-notes for each of those, and in doing so i have uncovered an edge case while using the AdvancedMappingCrud.Cosmos.Tests project regarding the Intent.CosmosDB.CosmosDBValueObjectDocument and Intent.CosmosDB.CosmosDBDocument templates.