简体   繁体   中英

how to implement time persistence in drools?

I am new to drools and I was wondering if there was a way to write rules that express persistence in time :

if (condition true for X seconds ) then doSomething()

Rule "Example"
when
  r: Room(Temperature > 100 for 10 minutes )
then
  doSomething()
end

There are two modes for firing Drools rules -- the default is "Cloud" mode, where we evaluate all of the facts in working memory at a single point in time. This is the oldest and most common way to fire rules. The other mode is "stream" mode, where data is played in continuously, and the Drools engine is aware of time.

When in stream mode, Drools has a set of temporal operators (link to Drools documentation) which can be used to write conditions against facts which occur over time.

One way that you can use the temporal operators for your use case would be as follows:

rule "Detect temperature over 100 for 10 minutes"
when
  $t: Temperature(this >= 100) from entry-point "TemperatureStream"
  not(
    Temperature(
      this != $t, 
      this < 100,
      this after[0s,10m] $t) from entry-point "TemperatureStream")
then
  doSomething()
end

This simple rule expects that you're sending Temperature events from an entrypoint ( TemperatureStream ) via some external mechanism. When it detects a temperature over 100 degrees (instance $t ), the first condition triggers.

The second condition is where the magic happens. The second condition will only trigger if it does not receive a Temperature event of less than 100 degrees in the 10 minutes following the receipt of $t .

As your monitoring application sends temperature events, each one over 100 will trigger the first condition, and then start monitoring the stream to see if the second holds true. If it does, the consequence of the rule will fire. Otherwise the rule match will be discarded.

Alternatively, you could use a sliding window over 10 minutes to see if the temperature minimum ever drops below 100.

rule "Detect temperature over 100 for 10 minutes - sliding window"
when
  not(
    Number(doubleValue < 100) from accumulate(
      Room( $temperature: Temperature ) over window:time(10m),
      min( $temperature )
    )
  )
then
  doSomething()
end

Here, window:time(10m) is a sliding window over a 10 minute period. Unlike the other solution which observes each even as it comes in, and then tries to check if a second condition matches, this one simply looks at all events over a period of time. If the minimum temperature never goes below 100 for the entire window, the right hand side triggers.

There's probably other ways of doing this, these are just the two that I came up with offhand. The documentation is particularly good for this part of Drools, so you might find another way that better fits your use case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM