Embrace event-driven web applications
A short saga
Raising your awareness
After over a decade of Dotnet web development, I’ve noticed that one of the most underused C# features is the event pub/sub. I’m not entirely sure why that is but I’ve noticed a general absence of event-driven programming which is very surprising considering how much event-driven programming is all around in a web environment.
Let’s look at all those events buzzing around.
Controlling your traffic
In a web application, the server makes first contact with a client typically through a controller. If you think about it, a controller responds to an event that we call a web request. Of course the “event” is delivered to us using HTTP protocols, we “respond” to that event with a reply. When we write the code, we don’t wonder where the request comes from, we are just expected to respond to it and handle it.
The internet would be boring if we had to browser web pages by issuing cURL commands manually. Thankfully, the almighty browser makes requests which manifest as events for our server-side. The browser may be the King of event generation.
The Browser
In the early days of the internet, there was an important decision that was made — the browser would render a UI that responded to events. If you’ve ever done anything in the browser (besides change some colors), then you’ve no doubt had to write some sort of “click” handler. You don’t need to be a JavaScript guru to know that the browser is raising an event, and you can write code to handle it. jQuery made event things easy before we collectively revolted against it.
In fact just about everything you do in the browser raises events. You can even issue your own custom event easily. Each event can be optionally handled through a tree of elements as the event bubbles upward to the root element. Without this mechanism, we’d have a really hard to writing immersive user-interfaces.
Pub/Sub
What makes events useful is the publisher (the emitter of the event) publishes to a medium which handles the subscriptions independently from the publisher. This means the publisher has no idea if there are any subscribers (or 100’s). Conversely the subscriber has no idea who the publisher was (unless it makes itself known through an object or identifier).
In this way there is a natural decoupling that happens. So long as an event is published to a medium, the subscriber doesn’t care. The publisher really doesn’t care if it has any subscribers or not.
Get on the bus
Coming back to the backend, some of the most ubiquitous examples of event-driven programming are the bus and queue. Queues and busses can connect systems typically backed by async queues. Because of traffic loads and processing capacity, messages may take some time to process. You may be thinking that’s a negative, but in the end; async queues are a great way to scale up and not tie up valuable web requests waiting on work that can be done eventually.
In a queue setting, our publisher publishes to a “topic” (aka exchange for RabbitMQ fans). From there the message is no longer in the custody of the publisher. The topic then routes messages to subscribing queues — each with their own private copy of the event to handle as they see fit.
If you want to scale, you’ll be working with queues and splitting work that has to be done now versus work that can be done later. You’d be surprised at how much work can be deferred. My favorite pattern is the “coat check” pattern. In this pattern, a GUID (or some identifier) is given to the person requesting the work to be done and quickly sent away (web request ends). Think of the GUID as a claim ticket you’d get if you handed your coat to an attendant at a dry cleaner. Your “coat” is queued to be cleaned. While you’re out running errands, you can use your claim ticket to see the status of your dry cleaning. This pattern is great because the user literally doesn’t need to be logged in or worse — have the page spinning/loading the entire time. When completed, the dry cleaner can send a notification that the work is done.
Using a coat-check pattern is a godsend for handling long-running processes.
Saga Pattern
When using events, you cannot guarantee the order in which events might reach you. You may need to DoSomething(), but only after you’ve received two or more events.
A classic example happens when you need to store something in your database but the information for creating the entity will come from multiple messages. Since we cannot know for sure which message will come first, do we commit information from each message independently? What we really need to do is wait until we receive both messages before committing anything. When will we receive both messages? Will we ever receive them? What if the events can be days or months apart?
This problem is solved by using what is known as the Saga pattern. Essentially it’s a mechanism to let us define what ingredients we must have in our refrigerator before we can bake the cake. If we’re missing eggs, we won’t bother starting the oven.
I’m guessing the term “saga” was chosen because these events can arrive at very different times. Think about a financial transaction and all the different steps of the process. When each step completes, an event/message can be sent out and the saga mechanism can trigger the cake to be made because we now have eggs and milk.
An observation
Events are all around you in web development. Queues enable scaling with deferred execution, browser code mainly responds to UI events and events in-general expose the observer pattern. This pattern allows any interested bit of code to be notified and optionally react (handle) to the event.
C# events enable you to do the same thing, just within your own executing process. Once you see the events buzzing around you, it’s hard to not embrace event-driven architecture.

