Optimistic Concurrency in DocumentDB

Optimistic Concurrency in DocumentDBI’ve started working on new side project using ASP.NET Core.  I wanted to try a new datastore and decided to give Azure’s DocumentDB a try.

This project isn’t doing anything complicated but does contain enough real world use cases that can give me an idea of how the API works.

Concurrency

The first thing I needed to implement was how to handle concurrency.  Specifically optimistic concurrency.

In an optimistic concurrency model, a violation is considered to have occurred if, after a user receives a value from the database, another user modifies the value before the first user has attempted to modify it.

This is pretty typical when dealing with multi user environments like a web application.  Specifically in my case is:

  • Fetching out a document from DocumentDB
  • Mutating the data of the document
  • Sending the document back to to DocumentDB to be replaced

In my web application, the concurrency issue arises if the same document is being modified by multiple users at the same time.

Without having any type of concurrency, we are what is called a “Last Wins” mode.  Meaning, the last process/user that sends the document back to DocumentDB is what will be persisted.

ETags

Each document within DocumentDB has an ETag Property.

The ETag or entity tag is part of HTTP, the protocol for the World Wide Web. It is one of several mechanisms that HTTP provides for web cache validation, which allows a client to make conditional requests.

You may be familiar with ETag’s related caching.  A typical scenario is a user makes an HTTP request to the server for a specific resource.  The server will return the response along with an ETag in the response header.  The client then caches the response along with the associated ETag.

ETag: "686897696a7c876b7e"

If they client then makes another request to the same resource, it will pass a If-Non-Match header with the ETag it received.

If-None-Match: "686897696a7c876b7e"

If the resource has not changed and the ETag represents the current version, then the server will return a 304 Not modified status.  If the resource has been modified, it will return the appropriate 2XX status code along with the content new ETag header.

AccessCondition

DocumentDB uses ETags for handling optimistic concurrency.  When we retrieve a document from DocumentDB, it always contains an ETag property as apart of our document.

When we then want to send our request to replace a document, we can specify an AccessCondition with the ETag we received when we fetched out our document.

If the ETag we send is not current, the server will return a 412 Precondition Failed status code.  In our .NET SDK, this is wrapped up in a DocumentClientException.

Here is a full an example.

Demo Source Code

I’ve put together a small .NET Core sample with an XUnit test from above. All the source code for this series is available on GitHub.

Are you using DocumentDB? I’d love to hear your experiences so far along. Let me know on twitter or in the comments.


 

MediatR Behaviors

MediatR BehaviorsI was happy and surprised to see that MediatR v3.0 was released yesterday.  One of the new features, which I was really looking forward to are pipeline behaviors.

A pipeline behavior is an implementation of IPipelineBehavior<TRequest, TResponse>. It represents a similar pattern to filters in ASP.NET MVC/Web API or pipeline behaviors in NServiceBus.

Changes

There are a couple major breaking changes to v3.  All of them I’m fairly happy about actually.

Messages

There is no distinction between sync, async (cancellable) requests or notifications.

You simply implement either IRequest or INotification.

You must still create the appropriate handler via either IRequestHandler, IAsyncRequestHandlerICancellableAsyncRequestHandler.

Async

To send a request or publish a notification simply use Task Send(IRequest) or Task Publish(INotification)

No longer does it have the “Async” convention of appending to the method name.  I know this is often debated about this convention.  I don’t mind it at all since there are no sync methods.

Behaviors

The new addition is the interface IPipelineBehavior<TRequest, TResponse>

This allows you to create implementation(s) that will invoked in the order they are registered with your container (returned from the MultiInstanceFactory delegate).

The simplest implementation, that does nothing but call the next possible behavior.

You can see how you can use this to create Pre and Post behaviors to create a pipeline.

Pre & Post Processors

Thankfully, these have already been created and built-in to v3.

RequestPreProcessorBehavior<TRequest, TResponse> and RequestPostProcessorBehavior<TRequest, TResponse> to the rescue.

These can be used to implementing the appropriate interface of IRequestPreProcess<TRequest,TResponse> and IRequestPostProcessor<TRequest,TResponse>

Note: Be sure to register your  IRequestPreProcess<TRequest,TResponse> and IRequestPostProcessor<TRequest,TResponse> as well as RequestPreProcessorBehavior<TRequest, TResponse> and RequestPostProcessorBehavior<TRequest, TResponse>  with your container.

Test Drive

I figured I would use my ASP.NET Core MVC Music Store application as a test bed.

You can refer to my Fat Controller CQRS Diet: Command Pipeline post to see how created a pipeline in MediatR v2.  It involved creating wrapper/decorator with StructureMap.

This is incredibly straight forward and does all the heavy lifting that the pipeline decorator that I created previous.

For our MusicStore app, we can change our AddToCart for logging to be done like this.

The above code completely removed my need for my custom Pipeline decorator using StructureMap.  Win.

ASP.NET Extension

If you are using ASP.NET Core, check out the MediatR.Extensions.Microsoft.DependencyInjection v2.x package.  It has also been updated to support MediatR v3.

It adds several extension methods, one of which is IServiceCollection.AddMediatR(Assembly) to register all the Handlers and Pre/PostProcessor in a given assembly.

Comments

Are you using MediatR?  Do you plan on upgrading to v3?  I love hearing your comments, questions and recommendations!  Please post a comments or on Twitter.


Fat Controller CQRS Diet: Vertical Slices

This post is in my Fat Controller CQRS Diet series. It demonstrates how to thin your controllers by implementing commands and queries using the MediatR library.  Specifically in this post, I’ll look at organizing your code by vertical slices.

I’m converting the MusicStore application that’s using ASP.NET Core MVC.   All the source code is available on GitHub.

If you’re new to this series, here are earlier posts to get up to speed:

  1. Overview of Series
  2. Simple Query
  3. Simple Command
  4. Command Pipeline
  5. Notifications

Organize by Feature

Feature Slices or Vertical Slices are the terms I’ve heard the most for what I call Organize by Feature.

I’ve just always characterized as organizing all relevant code and files from a command or query into a specific folder or hopefully single file.

I generally stay away from creating layers so the term Vertical Slices does make a lot of sense.

Whatever our feature slice is, it surely makes sense to keep all that code together.

Single File

If you’ve seen the code related to my Command Pipeline or Notifications posts, then you should already be able to tell where I’m heading in terms of organization.

I generally like to keep the command/query and it’s associated handler all within the same file.  In the case of our logging handler, I was also keeping it in this file.

Pretty simple.  One file for everything related to a command or query.

Controllers & Views

Well almost.  What I hadn’t really moved were the controllers or views.  So let’s do that now.

Controllers are pretty easy since by default they can live anywhere within your project. ASP.NET MVC Core will just pick them up.

Let’s work on our Home Query.  We will simply create a HomeController within our Home.cs file that currently contains our query and our handler.

Because we are no longer using the default routing, I’ve added the HttpGet attribute to the method to keep the route intact to what it was prior.

View Locator

By default, ASP.NET Core MVC will look in the ~/Views/ folder with default conventions.  But we want to put our view right along side our Home.cs file in our Features folder.

So I’ve moved all of the view files into our Features folder.  Our solution now looks like this:

 

In order to tell ASP.NET where our views are now at, we can implement the IViewLocationExpander

Now in the  IServiceProvider ConfigureServices(IServiceCollection services) method from our Startup.cs, we can can configure to use our new locator.

That’s it!

We now have one file that contains our controller, query and handler.  And right along side it we have our associated view.

Comments

All the source code for this series is available on GitHub.GitHub

I love hearing your comments, questions and recommendations as it usually leads me down to other blog posts.  Please post a comments or on Twitter.