Ruleset parsing and the ruleset cache

Rulesets are parsed synchronously or asynchronously. With asynchronous parsing, which is set by default, execution of a new deployed version of a ruleset is not delayed by parsing. You can use a property to set ruleset parsing to synchronous.

Synchronous and asynchronous parsing

A version of a ruleset is deployed, parsed, and executed in a sequential process. Rule Execution Server supports both synchronous and asynchronous parsing for this process.
Synchronous parsing

When a new version of the ruleset is deployed, all execution is suspended until the new ruleset is parsed. Execution resumes when parsing is complete. As a consequence, the execution requests that have a newer version of the ruleset deployed on Rule Execution Server are kept waiting and therefore block the calling application.

Asynchronous parsing

If an older version of a ruleset exists in the loading order in cache, that older version is used for execution. The parsing of the new ruleset starts in a separate background thread. As a consequence, execution of a new deployed version of a ruleset is not delayed by parsing. Asynchronous ruleset parsing is the default option. See Scenario C for an example.

The following scenarios for asynchronous parsing describe the behavior of the execution unit (XU) with asynchronous parsing. In each scenario, the XU starts with an empty cache.

Remember:
  • Each ruleset has a unique canonical ruleset path in the following form: /{RuleApp name}[/{version}]/{ruleset name}[/{version}]

  • Execution paths can differ from deployment paths. When the execution path does not specify the version number, the execution process considers the last enabled version of the RuleApp and ruleset.

See Ruleset path for reference.

Scenarios for asynchronous parsing

Scenarios A, B, and C demonstrate three different cases of asynchronous parsing.

  1. In Scenario A, the ruleset is deployed and executed on the same path.
  2. In Scenario B, the ruleset deployment path and execution path are different.
  3. In Scenario C, three versions of the ruleset are deployed in different paths.
Scenario A: Same deployment and execution paths
In scenario A, the ruleset is both deployed and executed with the same ruleset path. The benefit is that a ruleset execution request is never stopped or suspended.
R1 = /a/1.0/b/1.0
R1' = /a/1.0/b/1.0
where
  • R1 is the current ruleset.
  • R1' is a new version of R1 with the same path.

Scenario A is played out as follows:

  1. Deploy R1.
  2. Execute R1.
  3. Deploy a new ruleset R1 named R1' with the same ruleset path /a/1.0/b/1.0.
  4. Execute R1.

    The execution uses R1 and parsing of R1' starts.

  5. Execute R1.

    Parsing of R1' is not complete, the execution uses R1.

  6. Parsing is R1' is complete.
  7. Execute R1.

    The execution uses R1'.

This scenario is typical in a production environment.

  1. The server receives ruleset execution requests continuously.
  2. Ruleset R1 is modified to R1'.
  3. The next request starts parsing ruleset R1' in the background.
  4. The execution of other rulesets is based on R1 until parsing of R1' is complete.
Scenario B: Different deployment and execution paths
In this scenario, different versions of the same ruleset are deployed on different paths:
R1 = /a/1.0/b/1.0
R2 = /a/1.0/b/2.0

The deployment paths for the two versions of the ruleset are different but the execution code does not specify the RuleApp and ruleset version numbers. Therefore, the client application executes the latest version of the ruleset.

Scenario B is played out as follows:
  1. Deploy R1.
  2. Execute /a/b.

    The execution uses R1.

  3. Deploy R2 to /a/1.0/b/2.0.
  4. Execute /a/b.

    The execution uses R1 while the parsing of R2 starts in the background.

  5. The parsing of R2 is finished.
  6. Execute /a/b.

    The execution process now uses R2.

In this scenario, version R2 of the ruleset is deployed with a different path. The execution process considers the last versions of R1 while the subsequent request starts to parse version R2 in the background. Until the parsing of R2 is finished, the execution of other rulesets is based on R1, which is the previous version of the ruleset in the loading order. When the parsing of R2 is finished, the XU loads R2 and the next execution request uses this new version.

Scenario C: Noncanonical ruleset path
In this scenario, three versions of the ruleset are deployed on different paths.
R1 = /a/1.0/b/1.0
R2 = /a/1.0/b/2.0
R3 = /a/1.0/b/3.0
Scenario C is played out as follows:
  1. Deploy R1 with a path /a/1.0/b/1.0.
  2. Execute /a/b.

    The execution process uses R1.

  3. Deploy R2 with a path /a/1.0/b/2.0.
  4. Deploy R3 with a path /a/1.0/b/3.0.
  5. Execute /a/b.

    The execution process uses R1 while the parsing of R3 starts in the background.

  6. The parsing of R3 is finished.
  7. Execute /a/b.

    The execution process now uses R3.

In this scenario, ruleset R2 is deployed but never executed because the XU has not loaded it. In such cases, the XU takes the previous version (R1) of the ruleset to be executed within its cache and ignores the logical order of the versions.

Asynchronous parsing suitability

Asynchronous parsing is pertinent in circumstances where the timely execution of a ruleset is paramount. In such cases, waiting for a new ruleset to be parsed is not an option and you must use the default parsing mechanism. Apply synchronous parsing of your rulesets if you want to use always the last ruleset version. To do so, set the asynchronousRulesetParsing property in the XU deployment descriptor to false. This setting prevents the use of an old ruleset until the parsing of the new ruleset is finished. The property value applies to all ruleset executions within the XU instance.

On the client-side, you can use the IlrSessionRequest.setForceUptodate method to insist that what is executed is the most up to date version of the ruleset. See Setting up ruleset parsing.

Implementation details

The XU uses the Work Manager API to grant an application access to a container-managed thread. The Work Manager API provides a mechanism to join various concurrent work items, so that an application can programmatically add the dependency of work completion as a condition for starting other tasks. The Work Manager API defines "Work" as a unit of work, which you want to execute asynchronously. Server administrators must create WorkManager by defining it in the Java™ EE container configurations.

Note:

Asynchronous parsing is also supported in Java SE. In this environment, the connection manager implemented by Decision Server is simple: the "Work" items are directly mapped to Java threads without any actual management. Therefore, you do need to change any configuration settings.

Ruleset cache

The XU uses a cache of ruleset instances to avoid parsing rulesets for each execution. By default, a ruleset stays in memory if at least one connection in the JCA connection pool references it. Even if the JCA connection is not active, it references rulesets until the application server deletes them. When a ruleset is no longer referenced by a JCA connection, that ruleset is available for garbage-collection. This default behavior ensures that unused rulesets are removed from the memory.

You can retrieve ruleset usage information from a XU plug-in or from a ruleset cache implementation. You can customize the ruleset cache by writing your own implementation class and modifying the XU configuration file ra.xml accordingly.

Ruleset timeout

Ruleset parsing consumes processor power and memory and slows down the entire ruleset execution process. You can define how long a ruleset stays in memory by setting the value of the ruleset.maxIdleTime ruleset property in the Rule Execution Server console. Timeout values are useful to ensure that rulesets with a long parsing time are kept in memory even if the ruleset is not referenced by a JCA connection.

You can set the following values:
  • -1 or undefined: the ruleset is removed from the cache, depending on how the ruleset is used by the JCA connection pool. The ruleset is eligible to garbage collection as soon as no SPI connection references it.
  • ≥ 0: the ruleset is removed from the cache after the timeout (in seconds) is reached and no SPI connection references it.
  • 0: the ruleset is never removed from the cache except if the ruleset is redeployed.
    Important: Use this value with caution because it might introduce a significant memory leak if the ruleset is never used.

The XU periodically runs a maintenance task to manage the timeout policy. You must define the period in seconds in the XU configuration file, as follows:

<config-property>
   <config-property-name>rulesetCacheProperties</config-property-name>
   <config-property-type>java.lang.String</config-property-type>
   <config-property-value>ruleset.cache.maintenance.period=30</config-property-value> 
</config-property>
For more information, see Managing the XU timeout policy.