As I mentioned in my previous post on Azure Function basics, Functions are self contained code that are initiated with a trigger. This makes Functions extremely useful when working with Event driven architectures where your application is responding to discrete events. This week I spent a bit of time away from playing with the technology I’m using to build a Discord Bot and really started to plan out how to build the features. Let’s take a look at the process I’m using to design this system, as well as the thinking behind it.
Why Event Based
Firstly, why did a settle on a Event-driven / Azure Functions based application? At it’s core, my Discord Bot project] is essentially a chat bot, with a number of different non-related chat features added in. Most, if not all, chat bots essentially sit idle until the user interacts with it. This makes it an ideal use case for designing the bot in such a way as a chat bot just responds to events. The Discord API itself revolves are exposing these events, and essentially wiring up Azure Functions to process these events offers a number of benefits, including:
- The ability to scale out a single event processor component if required
- Modify and test small sections of the entire application
- Encourages development of functionality in a modular way
Flow Charts For Event Maps
Mapping processes using Business Process Modeling Notation or even flow charts is a common technique for designing applications. Using this sort of technique is also quite useful for breaking down event based responses. The above image is a high level breakdown of the initial functional flow I’m building into the Discord bot. At the moment my bot essentially handles two events from the Discord server - “Guild Join” and “Message Sent”. These messages are user initiated events (designated with a circle) that are then sent to various Functions (designated with a rectangle) for processing. The lines represent the communication channel between processing points, such as Event Hubs or Storage Queues.
General Rule of Thumb
By breaking down the process and functions within an application to this lower level you can implement each step as a independent Function application. Some good rules of thumb for breaking down your processes this way are:
- If a step can be broken into two or more steps, consider splitting the step.
- If one step strongly requires another step, consider joining the steps.
- If you need to work closely with state or require speed between steps, consider joining the steps
- If a step can be reused, try to make the steps as generic as possible for reuse.
Benefits and Disadvantages
This flow chart is a fairly small, limited functionality application but you should already be able to see some of the benefits, including:
- The Log Server Function, if written generically, can be reused to save any type of event
- The Check Message Details can be scaled up to process lots of events independently of the rest of the application
- I can use any combination of Event Hubs, Service Bus or Storage Queues between functions, depending on my requirements.
- I can change, test and replace components of my application while my application is running (generally speaking).
There are some downsides to this sort of architecture as well however, including:
- Applications become more complex - there is a lot of moving parts.
- You require a mix of technologies to implement functionality
- If you require state information, you need to store and read it from something like a database, table storage or a cache
Hopefully this gives you some insight into a way to structure and design your application in a way to take advantage of Azure Functions. This method also gives you a good way to track where and how your Functions are structured together.