Imagine you have a system with dynamic business rules, that your client wants to change on a regular basis. This rule engine is used by scheduled background processes and helps your client in terms of managing their infrastructure.
So your client suggests that the rules should be stored in an MSSQL table so that they can easily create a user interface that reads and writes the business rules. To make things really easy for your client, the rules should not be expressed as JSON (the default format used by the rule engine, like this one), but instead, be persisted in a plain tabular format. After all, most GUI builders work with traditional RDBMS systems.
Rules Engine Architecture
So you end up with an architecture that looks like this:
These are the main components of our architecture:
- Microsoft PowerApps helps you to build custom apps that can easily connect with RDBMS systems like Microsoft's MSSQL database.
- Our rule engine will be embedded inside of an Azure Function, which then reads the rules from the Microsoft's MSSQL database. If you want to know how you can embed a rule engine in an Azure Function, please check this blog for more information.
- A workflow process running on Azure Logic Apps will use a REST API for sending data and receiving the outcomes of the rules engine, which lives inside of an Azure Function.
The Missing Link
So this sounds like a good architecture, but something is missing. How do you bring the rules expressed in tabular format into your rules engine?
The missing link is highlighted in a red bubble below:
A Small Framework For Saving and Retrieving Rules in a Tabular Format
We have created a small framework to bring rules in a tabular format into the format of our JSON based rule engine: the json-rules-engine.
The first thing that we needed was a representation of rules in a tabular format. To achieve this, we need first to understand what a rule and a logical condition are:
- a rule is a container of logical conditions that can be combined either by an OR ("any") or AND ("all") logical operators. A rule also triggers an event in case it evaluates to true.
- a logical condition is the association of a fact (field in a data record) with an operator and a value.
Here is an example of a logical condition in JSON format:
Here is a simple rule in JSON format, which combined two logical conditions with an AND operator ("all"):
This simple rule triggers an event in case two meteorological conditions are satisfied. So if the windspeed is greater than 15 mph and the precipitation is greater than 155 mm a device is shut down.
Sometimes rules can be nested in other rules, thus allowing multiple combinations of OR and AND rules. So there is a need to have rules which have other rules as their children, like, e.g.:
The Rules Schema
It was only necessary to create two tables to represent our rules data model:
We have a rule condition entity with a many-to-one relationship to the rule definition entity. The rule definition also has a one-to-many relationship with itself, i.e. a rule definition can have multiple children, but only a single parent.
This simple schema together with some conversion code is enough to create the JSON rules depicted above.
The Conversion Library
If you want to convert the content of our relational rules database to a JSON file, you can execute this code:
This is what the createRules function does internally:
- It queries the database and outputs a flat list of conditions associated with their respective rules. It executes this query:
- It then loops through the list of all conditions + rule and aggregates the conditions per rule. At the end of this process, you will have a list of rules with a list of conditions and the symbols used in the database will also have been converted to the symbols used by the json-rules-engine library.
- It then builds the hierarchy of the rules recursively.
For more details you can check the code in our Git repository:
Using Microsoft Azure-based technologies allows you to build powerful rules-based systems, including REST-based rule execution with workflow integration, with proper rules storage and a GUI (graphical user interface), that allows business users to create and change rules. Since most rule engines come with their own native format, you will need to convert the RDBMS based format into the native format of your rules engine. This can be achieved using a basic rules schema and the example project we presented in this blog.