The flowchart below illustrates one run to completion (RTC) cycle, which generally begins when an external action causes changes to working memory. One RTC cycle ends when there are no more rule actions to execute as a result of that initial change. This is also known as
forward chaining, or
inferencing. During one RTC no new external actions can affect the working memory. An RTC is composed of one or more
conflict resolution cycles. A conflict resolution cycle begins when BusinessEvents builds (or refreshes) a
rule action agenda, which is used to determine which rule action to execute, and ends when a rule action is executed (or the agenda is empty). If the rule action changes working memory, another conflict resolution cycle begins. Sections following the flow chart provide more detail.
Working memory changes The first of the conflict resolution cycles is initiated by change in working memory caused by an external action such as a message arriving at a destination.
All other changes to working memory during one run to completion cycle (RTC) occur because of rule actions. When there are no remaining rule actions on the agenda, the run to completion cycle ends. The next cycle begins with another change from an external source.
BusinessEvents builds the agenda To build the rule action agenda, BusinessEvents examines all rules that are
newly true because of the change to working memory and compares them with rule dependencies. See
How a Rule Becomes Newly True and How Conflict Resolution Uses Rule Dependencies for more details. The agenda’s entries are ordered according to rule priority and other criteria.
An empty agenda ends the RTC At some point, no more actions remain to be executed. The conflict resolution has run to completion.At the end of one RTC the following happens (depending on how the project has been configured:
As stated above, the rule action agenda is built by examining all rules that are newly true. A rule is
newly true if it has become true due to a change in working memory.
Less obviously, a rule that was already true can also become newly true. For example, a rule may already be true because a condition that specifies a range is satisfied. It becomes newly true if the property value in working memory changes but is still within the range. For example, the condition
c.b<10; is true if working memory includes a
c.b with value
9. It is newly true if an action at the end of a conflict resolution cycle changes the value from
9 to
8.
A rule is removed from the agenda because a change in working memory during an RTC means that the facts no longer satisfy its dependency set, for example because a concept instance is deleted or a concept property changes value.
Before any data enters the system, BusinessEvents builds the Rete network, which embodies all the
rule dependencies, using the rule conditions (if any). All the dependencies in a rule are called its
dependency set. A rule’s dependency set is everything needed to determine the truth of all the conditions. For example, a rule has this condition:
Where c is a concept of type /Customer. In this case, the dependency set of the rule contains only the
name property of the concept type
/Customer. As another example, suppose a rule has these conditions:
Where b is another concept type and
num is one of its properties. The dependency set for that rule is
b.num and
c.
During a conflict resolution cycle, BusinessEvents tests each rule’s dependency set against the new set of facts. If the facts match the rule dependencies, the rule conditions are all true and the rule action is added to the rule action agenda. The structure of the Rete network enables very quick matching between facts and rule dependency sets.
If BusinessEvents cannot calculate dependencies on the properties of an entity from the rule condition, for example if you pass an entity to a function, BusinessEvents evaluates the rule every time the entity or its properties changes.
Class filters are the least expensive operations, in terms of processing cost, and non-equivalent joins are the most expensive. To optimize performance, ensure that as much filtering as possible is done first, to reduce the number of objects for which an expensive condition must be evaluated.