Rules engines in general have a well known way of processing data and rules and provide the application with the results. Also, there is not many requirements on how facts should be presented to the rules engine, specially because in general, the processing itself is time independent. That is a good assumption for most scenarios, but not for all of them. When the requirements include the processing of real time or near real time events, time becomes and important variable of the reasoning process.
The following sections will explain the impact of time on rules reasoning and the two modes provided by Drools for the reasoning process.
The CLOUD processing mode is the default processing mode. Users of rules engine are familiar with this mode because it behaves in exactly the same way as any pure forward chaining rules engine, including previous versions of Drools.
When running in CLOUD mode, the engine sees all facts in the working memory, does not matter if they are regular facts or events, as a whole. There is no notion of flow of time, although events have a timestamp as usual. In other words, although the engine knows that a given event was created, for instance, on January 1st 2009, at 09:35:40.767, it is not possible for the engine to determine how "old" the event is, because there is no concept of "now".
In this mode, the engine will apply its usual many-to-many pattern matching algorithm, using the rules constraints to find the matching tuples, activate and fire rules as usual.
This mode does not impose any kind of additional requirements on facts. So for instance:
There is no notion of time. No requirements clock synchronization.
There is no requirement on event ordering. The engine looks at the events as an unnordered cloud against which the engine tries to match rules.
On the other hand, since there is no requirements, some benefits are not available either. For instance, in CLOUD mode, it is not possible to use sliding windows, because sliding windows are based on the concept of "now" and there is no concept of "now" in CLOUD mode.
Since there is no ordering requirement on events, it is not possible for the engine to determine when events can no longer match and as so, there is no automatic life-cycle management for events. I.e., the application must explicitly retract events when they are no longer necessary, in the same way the application does with regular facts.
Cloud mode is the default execution mode for Drools, but in any case, as any other configuration in Drools, it is possible to change this behavior either by setting a system property, using configuration property files or using the API. The corresponding property is:
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); config.setOption( EventProcessingOption.CLOUD );
The equivalent property is:
drools.eventProcessingMode = cloud
The STREAM processing mode is the mode of choice when the application needs to process streams of events. It adds a few common requirements to the regular processing, but enables a whole lot of features that make stream event processing a lot simpler.
The main requirements to use STREAM mode are:
Events in each stream must be time-ordered. I.e., inside a given stream, events that happened first must be inserted first into the engine.
The engine will force synchronization between streams through the use of the session clock, so, although the application does not need to enforce time ordering between streams, the use of non-time-synchronized streams may result in some unexpected results.
Given that the above requirements are met, the application may enable the STREAM mode using the following API:
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); config.setOption( EventProcessingOption.STREAM );
Or, the equivalent property:
drools.eventProcessingMode = stream
When using the STREAM, the engine knows the concept of flow of time and the concept of "now", i.e., the engine understands how old events are based on the current timestamp read from the Session Clock. This characteristic allows the engine to provide the following additional features to the application:
Sliding Window support
Automatic Event Lifecycle Management
Automatic Rule Delaying when using Negative Patterns
All these features are explained in the following sections.
When running the engine in CLOUD mode, the session clock is used only to time stamp the arriving events that don't have a previously defined timestamp attribute. Although, in STREAM mode, the Session Clock assumes an even more important role.
In STREAM mode, the session clock is responsible for keeping the current timestamp, and based on it, the engine does all the temporal calculations on event's aging, synchronizes streams from multiple sources, schedules future tasks and so on.
Check the documentation on the Session Clock section to know how to configure and use different session clock implementations.
Negative patterns behave different in STREAM mode when compared to CLOUD mode. In CLOUD mode, the engine assumes that all facts and events are known in advance (there is no concept of flow of time) and so, negative patterns are evaluated immediately.
When running in STREAM mode, negative patterns with temporal constraints may require the engine to wait for a time period before activating a rule. The time period is automatically calculated by the engine in a way that the user does not need to use any tricks to achieve the desired result.
For instance:
Example 2.11. a rule that activates immediately upon matching
rule "Sound the alarm" when $f : FireDetected( ) not( SprinklerActivated( ) ) then // sound the alarm end
The above rule has no temporal constraints that would require
delaying the rule, and so, the rule activates immediately. The following
rule on the other hand, must wait for 10 seconds before activating, since
it may take up to 10 seconds for the sprinklers to activate:
Example 2.12. a rule that automatically delays activation due to temporal constraints
rule "Sound the alarm" when $f : FireDetected( ) not( SprinklerActivated( this after[0s,10s] $f ) ) then // sound the alarm end
This behaviour allows the engine to keep consistency when
dealing with negative patterns and temporal constraints at the same time.
The above would be the same as writing the rule as bellow, but does not
burden the user to calculate and explicitly write the appropriate duration
parameter:
Example 2.13. same rule with explicit duration parameter
rule "Sound the alarm" duration( 10s ) when $f : FireDetected( ) not( SprinklerActivated( this after[0s,10s] $f ) ) then // sound the alarm end