CQRS in Azure - Part 2
In CQRS in Azure Part 1, CQRS was defined and context was provided to explain why the pattern is relevant to building solutions in Azure. This post will illustrate the pattern by using a fictitious inventory system in order expand on the advantages while providing potential strategies for addressing the challenges that arise when moving away from the traditional monolith solution.
A sample project illustrating some of the approaches described is available on MSDN Samples: CQRS in Azure.
The Old Pie Shoppe
Take a simple scenario of a pie shop managing their inventory. The business team determine they want a single view of the inventory across the different storage locations. The designer comes up with a dashboard that allows for the inventory to be displayed and updated.
The architecture team then puts forth the following design (of course leaving out the great things Azure delivers as part of the solution like load balancing, backup etc. 😁 ):
Great. Everyone is happy. The design shows a clear separation between the reading of the inventory and the updating of inventory. The expectation is the majority of the traffic will be on the website and it can be scaled independently from the function. Another advantage is the building of the website and the function will be done by different teams.
Challenges
There are a number of challenges that will be explored through this example. For example, the adoption of the architecture as this approach deviates from the companies previous approaches to building websites. Staleness in the browser as well as dirty reads from application cache and potential concurrency issues when writing to the back-end database.
Challenge 1: Adoption
Even with such a simple design there are many ways this could be put together. A more traditional approach would of course be to use the website as conduit for the requests.
There are merits to this approach though the most compelling reason is that the approach is the de facto approach of the development team. Also, complexity like cross-origin resource sharing (CORS) does not have to be resolved by the team (though with Azure WebApps support for CORS this is not a large issue). A more compelling argument from the development team is if the message goes through the website then the website will know to refresh its view of the model. So good microservice-like intentions start to progress towards the monolithic website where our command is not separate from our request and all that was accomplished is to introduce the overhead of a service call.
Fortunately for this post, the architect's initial design stands. The fictitious reasoning is as follows. First the business is planning on introducing scanners to help track inventory. The scanning device supports integrating directly to the function and this is preferable over routing through the website. With the introduction of the devices, the load on the website will be reduced dramatically, and the load on the function will be increased. If direct integration with the scanners is introduced, the website will then no longer be able to reflect the model state based on the messages flowing through it.
Challenge 2: Staleness
If we revisit the diagram of our solution from the previous post, one issue that was identified was stale data being shown in the browser:
There are many approaches to addressing staleness and three common approaches are:
don't worry about it approach
This is the most common approach and in many business scenarios make the most sense as the latest information will be retrieved on the next page load.Javascript polling
A simple mechanism to refresh model state without a full page refresh is to use a Javascript timeout to create a periodic poll of the information. In the sample PieShop project, this is the approach used to refresh the dashboard with the latest information every 5 seconds and is shown below:function pollForInventory() { $.post('@Url.Action("GetInventory")', function (data) { /*do something */
setTimeout(pollForInventory, 5000); }); }
There are many client libraries available to facilitate this including providing enhancements like in browser caching and event subscriptions. Combined with server side long polling, this can be an effective approach to handling stale data.
Additional References
Simple Long Polling Example with JavaScript and jQuery JavaScript Polling
WebSockets
WebSocket based communication libraries support building real-time web applications by providing frameworks for bi-directional communication between client and server. Microsoft's SignalR provides a simple abstraction over the underlying WebSocket communication and provides fall back capability to long-polling when the browser lacks support the duplex communication. With SignalR, a hub can be created to push messages to individual clients as well as supporting broadcasting to multiple clients.
Next
CQRS in Azure - Part 3 will continue with the challenges of dirty reads from application cache and dirty writes to the database.
Hopefully the series is helpful. Please post in the comments suggestions for other ways of tackling the Old Pie Shoppe dashboard!
Comments
- Anonymous
April 04, 2017
Great one! Thanks! - Anonymous
April 05, 2017
Can't wait for Part 3!! - Anonymous
April 11, 2017
Very well written! This article is broken down very well with the diagrams and code. It makes it very easy to enjoy. =^) - Anonymous
May 01, 2017
Part 3 has been published: https://blogs.msdn.microsoft.com/azuredev/2017/04/14/cqrs-in-azure-part-3/