Drools rule firing - drools

I have event driven architecture. Say about 1000 event types and each event type can have multiple listeners. Averaging around 2 per event. giving 2000 handlers.
For each event handler I have rule to be evaluated further to see if that event handling is required or not.
handle(MyEvent xxx){
kisession.execute( xxx.getPayload());
// Here I want the rules that are named/identified againt my Event alone to be fired
}
I could add MyEvent to be part of LHS of the specific rule.
But I want the matching to be preprocessed to save on processing time after event is fired.
Is there a better way to fire a specific rule only rather than allowing the underlying engine evaluate all the 2000 rules to figure out which one is applicable for the Payload fact?
I could identify the rules for specific event handlers at design time itself and want to exploit this advantage for better performance.

If you select which rule to fire from outside the rules engine, then there is absolutely no point in using a rules engine!
Evaluating which rules should activate is what Drools is designed to do. Fast. Drools does not need to evaluate 2000 rules every time you call fireAllRules, just because you have 2000 rules. When you create a knowledge base, the rules are compiled into a graph which lets the engine determine which rules might fire for certain matches. The graph is updated every time a fact is inserted, modified or retracted. It's a bit like having an indexed database table.
Of course, you can technically do this. Use the fireAllRules(AgendaFilter) method to filter the rules which may fire.

Related

How do I know which drools rule is running now?

For example, I am load a lot of drools rules to run, how do I know which drools rule now is running? So I can know find out the rule
Assuming you're talking about the right hand side of the rules, you'll want to use an AgendaEventListener. This is an interface which defines a listener that you can create that watches the Event Lifecycle. For more information about the event model, please refer to the Drools documentation.
The easiest way to do this would be to extend either DefaultAgendaEventListener or DebugAgendaEventListener. Both of these classes implement all of the interface methods. The Default listener implements each method as a "no-op", so you can override just the methods you care about. The Debug listener implements each method with a logging statement, logging the toString() of the triggering event to INFO. If you're just learning about the Drools lifecycle, hooking up the various Debug listeners is a great way to watch and learn how rules and events process in rules.
(Also the cool thing about listeners is that they allow you to put breakpoints in the "when" clause that trigger when specific conditions are met -- eg when a rule match is created. In general I find that listeners are a great debugging tool because they allow you to put breakpoints in methods that trigger when different parts of the Drools lifecycle occur.)
Anyway, what you'll want to do is create an event listener and then pay attention to one or more of these specific events:
BeforeMatchFired
AfterMatchFired
MatchCreated
Which events to pay attention to depend on where you think the issue is.
If you think the issue is in the "when" clause (left-hand side, LHS), the MatchCreated event is what is triggered when Drools evaluates the LHS and decides that this rule is valid for firing based on the input data. It is then put on, effectively, a priority queue based on salience. When the rule is the highest priority on the queue, it is picked up for firing -- at this point the BeforeMatchFired event is triggered; note that this is before the "then" clause (right-hand side, RHS) is evaluated. Then Drools will actually do the work on the RHS, and once it finishes, trigger the AfterMatchFired.
Things get a little more complicated when your rules do things like updates/retracts/etc -- you'll start having to consider potential match cancellations when Drools re-evaluates the LHS and decides that a rule is no longer valid to be fired per the facts in working memory. But in general, these are the tools you'll want to start with.
The way I would traditionally identify long-running rules would be to start timing within the BeforeMatchFired and to stop timing in the AfterMatchFired, and then log the resulting rule execution time. Note that you want to be careful here to log the execution of the current rule, tracking it by name; if your rule extends another rule you might find that your execution flow goes BeforeMatchFired(Child) -> BeforeMatchFired(Parent) -> AfterMatchFired(Parent) -> AfterMatchFired(Child), so if you're naively stopping a shared timer you might start having issues. My preferred way of doing this is by tracking timers by rule name in thread local or even a thread-safe map implementation, but you can go whichever route you'd like.
If you're using a very new version of Drools (7.41+), there is a new library called drools-metric which you can use to identify slow rules. I haven't personally used this library yet because the newest versions of Drools have started introducing non-backwards-compatible changes in minor releases, but this is an option as well.
You can read more about drools-metric in the official documentation here (you'll need to scroll down a bit.) There's some tuning you'll need to do because the module only logs instances where the thresholds are exceeded. The docs that I've linked to include the Maven dependency you'll need to import, along with information about configuration, and some examples of the output and how to understand what it's telling you.

Is rule engine suitable for validating data against set of rules?

I am trying to design an application that allows users to create subscriptions based on different configurations - expressing their interest to receive alerts when those conditions are met.
While evaluating the options for achieving the same, I was thinking about utilizing a generic rule engine such as Drools to achieve the same. Which seemed to be a natural fit to this problem looking at an high-level. But digging deeper and giving it a bit more thought, I am doubting if Business Rule Engine is the right thing to use.
I see Rule engine as something that can select a Rule based on predefined condition and apply the Rule to that data to produce an outcome. Whereas, my requirement is to start with a data (the event that is generated) and identify based on Rules (subscriptions) configured by users to identify all the Rules (subscription) that would satisfy the event being handled. So that Alerts can be generated to all those Subscribers.
To give an example, an hypothetical subscription from an user could be, to be alerted when a product in Amazon drops below $10 in the next 7 days. Another user would have created a subscription to be notified when a product in Amazon drops below $15 within the next 30 days and also offers free one-day shipping for Prime members.
After a bit of thought, I have settled down to storing the Rules/Subscriptions in a relational DB and identifying which Subscriptions are to fire an Alert for an Event by querying against the DB.
My main reason for choosing this approach is because of the volume, as the number of Rules/Subscriptions I being with will be about 1000 complex rules, and will grow exponentially as more users are added to the system. With the query approach I can trigger a single query that can validate all Rules in one go, vs. the Rule engine approach which would require me to do multiple validations based on the number of Rules configured.
While, I know my DB approach would work (may not be efficient), I just wanted to understand if Rule Engine can be used for such purposes and be able to scale well as the number of rules increases. (Performance is of at most importance as the number of Events that are to be processed per minute will be about 1000+)
If rule engine is not the right way to approach it, what other options are there for me to explore rather than writing my own implementation.
You are getting it wrong. A standard rule engine selects rules to execute based on the data. The rules constraints are evaluated with the data you insert into the rule engine. If all constraints in a rule match the data, the rule is executed. I would suggest you to try Drools.

Is rule selection in Drools nondeterministic or random?

Consider in Drools a set of rules that make up an activation group, all of them have the same salience and all of them are activated. Because they are in an activation group, only one of them can fire.
I want to know if the Drools engine makes sure that each of these rules has approximately the same chance of firing (selection is random) or if it is only formally undefined which rule will fire (selection is nondeterministic). In the latter case the rule fired would depend on the machine's state if anything and in practice e.g. almost always the top rule will fire.
Given that there are n rules with equal salience with all of them being activated: there is no randomizing being done by the engine to select the next rule to be fired, i.e., you can't use the engine to select a winner in a lottery.
There is something like a priority queue, and new activations are entered according to some efficient procedure. You may read that code or devise some test to determine how, but you should not base your application on these findings.

Is it possible to access the implicit timestamp of a Drools Fusion event?

I am trying to edit an existing Drools Fusion rule. The class we use for events does not have any kind of timestamp, so the rule is relying on the ones implicitly added by Drools at the time the events are created.
I would like to add some code to the "then" block of the rule to retrieve data from a database related to the times at which the events occurred. However, I can find no way to access these implicit timestamps.
Is there any way to do this, or am I going to have to re-define the event class?
You can access the timestamp if you have the handler when you insert the event.
As far as I know, there is no way to access it in the rule. This old article from 2012 makes some good points about the complexity.
http://drools-moved.46999.n3.nabble.com/Drools-Fusion-Accessing-Events-time-read-only-with-Drools-in-STREAM-mode-REALTIME-clock-td4020251.html#a4020256

Receiving notification of Drools logical retraction events

I have a knowledge base for performing validation of my data model. Modification events from the UI are posted asynchronously to a separate thread that updates the knowledge base and fires the rules. Validation errors trigger a logical insert of an error object. I can collect these and post events asynchronously back to the UI thread. However, to make it easier to keep the UI up-to-date, I also want to post an event when the user fixes an error – i.e. when an error object is retracted from the knowledge base.
I have two ideas for how to do this, neither of which I like:
I could listen to working memory events from procedural code, but that would violate the encapsulation of the validation functionality within the knowledge base.
Alternately, I could insert a flag object paired with my logical insertion of an error object and write a rule that detects un-paired flags, retracts them, and fires the "error fixed" event.
Is there a clean and simple way to activate a rule based on the logical retraction of an error object as described above?
Self-answering so that I can link to this later and find out if there is a better way to do it.
Here's the approach I wound up taking:
When a validation rule is triggered, insertLogical an object with a unique id representing the validation error (e.g. ValidationMessage).
ValidationMessage has a property "flagged", which defaults to false.
Define a rule that triggers on existence of unmarked ValidationMessages. In the RHS, mark the message and make an onAssert call to a global event handler. Insert a second object (e.g. ValidationMessageFlag) with the same id as the ValidationMessage.
Define a rule that triggers on existence of a ValidationMessageFlag, when no corresponding ValidationMessage (with the same id exists). In the RHS, call onRetract in the global event handler. Retract the ValidationMessageFlag.