Organizing (Commands, Events & Handlers) in Microservices

In a message-driven architecture such as SOA or Microservices, organizing commands and events, along with their respected handlers, can have a big impact on have you navigate your codebase. You might be surprised by the progression of how I organized them initially to what I do now! Also a tip on how to name commands and Events instead of after CRUD.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

Building Blocks

When moving into a message-driven system, you’re likely going to fall down the path of creating very explicit actions for your system rather than CRUD. When you do this, you’ll find yourself following CQRS and likely also moving to an event-driven architecture (where it makes sense).

The building blocks are messages and message handlers. Messages can be in the form of Commands, Queries, and Events. Commands and Queries will have a single handler that consumes the message. Events can have zero or many handlers that consume them.

Organizing commands and events (and their handlers) can be a bit of a message when you first start. I get asked often on my channel how I organize these building blocks of messages and handlers. Here’s how my progression over time.

Organize by Feature Folder

Put all relevant messages and handlers in the same folder. This is likely the most common or intuitive approach you might start with when moving into a message-driven system. Putting all the relevant types into their own files in a single folder.

I often put them nested inside a folder called Features. This is because I view a single or collection of messages and handlers as an individual feature. For example, setting an order as ReadyToShip is a command, but also occurs when the ShippingCreatedEvent occurs.

Single File with Suffix

The next step in the journey of organization for me was putting all relevant types into a single file. Especially for commands and queries, where there is only a single handler. To me, this simplifies not having to jump around files as the command/query and handler are directly related to each other. Why bother with two files?

The following example contains a Controller, Command, Handler, and Saga. Everything related to the feature of PlaceOrder is located in this file.

Events

In the above example, there is an OrderPlaced event that is published. However, it is not defined in this file. This is because this event is consumed and shared with other boundaries/services. For that reason, I put shared messages into a Contracts project which is shared with other services.

Static Wrapper Class

My next progression in organizing was I did not like having a redundant name for Command/Handler/Event. In the above examples for the PlaceOrder feature, there was a PlaceOrderCommand and PlaceOrderHandler. I found the naming to be a bit redundant and tiresome for typing.

To combat this, I simply place the types inside a static class. The static class is the name of the feature.

In the following example, the feature CancelOrder contains a static class named that, and nested within are the Command and Handler. When creating a new instance of a command: new CancelOrder.Command()

Suffix & Consistency

I tend not to suffix events with “Event”. Hence why you see OrderPlaced and OrderCancelled and not OrderPlacedEvent or OrderCancelledEvent. This is a matter of preference because events are always named in the past tense.

At the end of the day, it’s your preference. My recommendation is ultimately to be consistent in your naming. Regardless of how you organize or name, just be consistent as it will make navigating your codebase that much easier.

Source Code

Developer-level members of my CodeOpinion YouTube channel get access to the full source for the working demo application available in a git repo. Check out the membership for more info.

Additional Related Posts

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Smarter Single Page Application with a REST API

How can you build a smarter Single Page Application with a REST API? The concepts have been since the beginning of the web, yet have somehow lost their way in modern REST API that drives a Single Page Application or Mobile Applications. Here’s how to guide clients based on state by moving more information from design time to runtime.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

State

If you’re developing more than a CRUD application, you’re likely going to be driven by the state of the system. Apps that have Task Based UIs (hint: go read my post on Decomposing CRUD to Task Based UIs) are guiding users down a path of actions they can perform based on the state of the system.

The example throughout this post is the concept of a Product in a warehouse. If we have a tasks that let’s someone mark a Product as no longer being available for sale or it being available for sale, these tasks can be driven by the state of the Product.

If the given UI task is “Mark as Available” then the Product must be currently unavailable and we have a quantity on hand that’s greater than zero.

History of Clients

Taking a step back a bit, web apps were developed initially with just plain HTML (over 20 years ago for me). In its most basic form, a static HTML page contained a <form> that the browser rendered for the user to fill out and submit. The form’s action would point to a URI usually to a script, often written in Perl, in the cgi-bin folder on the webserver. The script would take the form data (sent via POST from the browser) and insert it into a database, send an email, or whatever the required behavior was.

As web apps progressed, instead of the HTML being in a static file, it was dynamically created by the server. But it was still just plain HTML.

The browser was the client. HTML was the content it’s consuming.

Modern Clients

As web apps progressed with AJAX (XMLHttpRequest) instead of using HTML forms, Javascript was used to send the HTTP request. The browsers turned more into the Host of the application which was written in Javascript.

Now, Javascript is the client. JSON is the content it’s consuming.

Runtime vs Design Time

Single Page Application with a REST API

When the Browser is the client consuming HTML, it understands how to render HTML. HTML has a specification. The browser understands how to handle a <form> tag or a <button>. It was driven by the HTML at runtime.

In modern SPAs consuming JSON, the data itself is unstructured. Each client has to be created uniquely based on the content it receives. This has to be developed at design time when creating the javascript client.

This is a shift from runtime to design time in modern clients.

When developing a SPA, you may leverage something like OpenAPI to generate code to use in the SPA/clients to make the HTTP calls to the server. But you must understand as a developer, at design time (when developing) when to make a call to the server.

To use my earlier example of making a product available for sale, if you were developing a server-side rendered HTML web app, you wouldn’t return the form apart of the HTML if the product couldn’t be made available. You would do this because on the server you have the state of the product (fetched from the database). If you’re creating a SPA, you’re likely putting that same logic in your client so you can conditionally show UI elements. It wouldn’t be a great experience for the user to be able to perform an action, then see an error message because the server/api threw a 400 because the product is not in a state to allow it to be available.

Hypermedia

Hypermedia is what is used in HTML to tell the Browser what it can do. As I mentioned earlier, a <form> is a hypermedia control.

When a user clicks the submit button, the browser is going to send a POST request to /mvc/save?Sku=123

The HTML is telling the Client (Browser) that his action is available.

Another hypermedia control is the <a> tag that is when clicked by the user in the browser, will then making an HTTP call to /mvc/images?Sku=abc123 and then render the returned HTML.

The HTML is telling the Client (Browser) where else it can navigate to.

The server is serving HTML that is providing the client with this information at runtime.

HTTP APIs

The vast majority of modern HTTP APIs serving JSON, do not provide any information in the content (JSON) about what actions or other resources the consuming client (SPA) can take. Meaning, we provide no information at runtime. All of that has to be figured out at design time.

In the example of a product, your typical response might look like this:

But how does your SPA know if it can mark the product as available for sale? Again, this is based on the state of the product, which your server knows since its returning you the state.

We can take the same concepts as forms and links and apply them to our modern HTTP APIs.

Now we’ve provided information at runtime to the client. If our client is developed at design time to know these links/actions may or may not exist, it can develop the appropriate UI to either show or hide certain functionality.

Now instead of being 100% design time, we’ve shifted more towards runtime.

You will still need to know (via OpenAPI) at design time, all the information about the routes you will be calling, and their results, however, you can now have the server return JSON that can guide the client based on state.

Media Types

This isn’t a new idea at all. Hypermedia in HTTP APIs exists with defined media types. Check out:

HAL http://stateless.co/hal_specification…
JSON API https://jsonapi.org/
Siren https://github.com/kevinswiber/siren
Hydra https://www.hydra-cg.com/spec/latest/…
JSON-LD https://json-ld.org/

Source Code

Developer-level members of my CodeOpinion YouTube channel get access to the full source for the working demo application available in a git repo. Check out the membership for more info.

Additional Related Posts

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

REST APIs for Microservices? Beware!

Are you using REST APIs for a Microservices architecture? If you’re using REST, HTTP APIs, gRPC, or any other Request/Response model as the primary way to communicate between microservices, you’re going to need to deal with possibly hard to debug latency issues and address availability concerns.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

In-Process Single Transaction

First, let’s take a step back and talk about a monolith. When in a monolith, you’d typically have a single process communicating with your database. If you’re using an ACID-compliant database, then you’d be using transactions to make all database statements atomic.

REST APIs for Microservices? Beware!

In the example above, our monolith has some clear boundaries of Sales, Catalog, Billing, and Warehouse. If an order is placed, which is started in sales, all three of these boundaries might be involved in that business process. Billing will have to create an Invoice and the Warehouse will have to allocate the products to ship. That entire business process would be encapsulated in one transaction. If anything goes wrong through that process, the transaction will rollback. We don’t have to worry about data consistency because we have the safety net of the atomic transaction.

Distributed Transaction

When you move out of a single process and into a distributed system, you’re going to lose that single database connection and transaction.

If you’re developing a microservices architecture with REST APIs, then what happens to your single transaction?

In the same scenario as above, when placing an order, there are multiple services that are required as apart of this long-running process.

If all the interactions from Sales to Billing and Warehouse are done over a REST HTTP API (or any synchronous request/response), then all the dependent services must be available in order to place an order.

If an order was placed, then Sales called Billing to create an Invoice and it succeeded. Then it calls the Warehouse to allocate products for shipping. If that request to the Warehouse fails, for whatever reason, then we have to manually perform some “undo” or compensating action to try and revert out changes along the way. This means you must make a call back to Billing to cancel the invoice.

But what happens if the request to cancel the Invoice in Billing fails? Now you’ve created an order, that has an invoice, has no allocated products.

REST APIs for Microservices? Beware!

Since there is no single transaction, you need a distributed transaction (or a two-phase commit). One way to solve this is what a transaction coordinator. But this means that all services must be using compatible technologies for databases. The likely hood of this is not high if you haven’t planned this initially.

The solution to this is through Event orchestration or choreography. But hang on, before that, there are more issues to discuss.

Latency

When making a network hop, you’re going to add latency. The issue is, if you’re inside one service, making an HTTP call to another service, that’s where the visibility ends. You are unaware of what the internals are of the other service is that you’re calling. What happens when the service you’re calling, has to call another service? And so on!?

In the example above, there is a network call chain from service to service. If each service takes (on a happy path) 200ms to respond to the other service, in my example above, it would take a total of 800ms roundtrip to the client.

REST APIs for Microservices? Beware!

The above is a best-case scenario. But because there’s so much coupling, that can’t directly be seen, latency can skyrocket if availability issues arise anywhere in the call chain.

What happens if the catalog is having performance issues and isn’t responding at 200ms, but at 700ms?

From our client, this is now going to take 1.3s. All because of downstream issues that are going to be very difficult to identify. From the perspective of Sales, it’s getting a slow response from the Warehouse. But the warehouse is getting a slow response from Billing. Who’s fault is it? Clearly, in my diagram, it’s the Catalog service, but without clear metrics, this is going to be very difficult to address. Beyond that, every network hop added in any downstream service is going to add latency.

Distributed Ball of Mud

It gets worst. The reality is if a service must make HTTP calls to other services, either for getting data or performing an action, then all the dependent services must be available for it to perform correctly.

For example, let’s say that Sales, Warehouse, and Billing all require the Catalog Service. If the Catalog service is unavailable or is having performance issues, then not only is it an issue, all the services are going to be failing.

This is a distributed monolith. Services require each other to be available and cannot function without other services.

Boundaries & Asynchronous Messaging

One solution to this distributed monolith is using asynchronous messaging between well defined boundaries.

Services should be autonomous. They shouldn’t depend directly on other services through synchronous interactions. If communication is done asynchronously through messaging, this means a service does not require other services to be available.

In order to make services autonomous, you need to have boundaries defined correctly. This means focusing on the behavior of the services and then the data required for those behaviors.

Once you have well-defined boundaries around capabilities, then you can use asynchronous messaging to define the workflow. Check out my post on Event Choreography and Orchestration to develop long-running business processes between services.

Source Code

Developer-level members of my CodeOpinion YouTube channel get access to the full source for the working demo application available in a git repo. Check out the membership for more info.

Additional Related Posts

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.