drools time based constraints and “now”

旧巷老猫 提交于 2020-01-11 12:14:18

问题


We are trying to write a drool which says something like "If the event happened in the last week, execute the consequence". We have regular java date objects representing the time the event happened, but we aren't sure how to express in the LHS of a drool that we want that date object to have taken place in the last week. Importantly, the timespan of a week is arbitrary. It could change to month or year at any time. Finally, keep in mind that our session is stateful.

I found a somewhat related question here: use java.util.Date in a rule's LHS . I will quote the most relevant excerpt from the answer below:

If you are executing within a stateless session, then your approach will work in combination with the Fusion operators. It is still not a recommended practice, however. A better approach is to define a fact, call it Now, which contains a single Date field. Initialize and insert it along with your other facts then reason against it instead of a global.

If you have a stateful session, it gets more tricky because real time is passing even while the session is idle, meaning your Now fact is getting more and more out of date. The way we have solved this is via the use of a WorkingMemoryEventListener. We use the objectInserted, objectRetracted, and objectUpdated methods of this listener to keep our Now fact current (we do not care about precision less than one minute so we check whether a minute has passed from the last update to avoid unnecessary overhead). Rules won't evaluate if working memory isn't changing, so using this listener is sufficient to ensure that Now is updated when it needs to be (unless you have queries that depend on the current value of Now, but that's another topic).

In the answer, the author describes problems with the representation of "now". His solution seems hacky and the answer was posted in a much earlier version of drools. I'm making a new question here to give better attention to this question specifically rather than the passing treatment it gets in the one I linked.

UPDATE:

Timestamps are the simple java.util.Date object.

Events are added to the session via api call. The stateful session is an object held by a java based api. The api adds events to the knowledge session when they are submitted. FireAllRules occurs about once per second.


回答1:


The fundamental question (as so often) is what the requirement really means. An event "happening in the last week" could be anything happening 7*24*60*60 seconds ago; it could be something that has happened from Monday 20151228 up to now, or from Sunday 20151227 until now, or maybe something similar where just the date matters and not the time of the day.

Ask what it really means, and rephrase your question accordingly.

If you do need a sliding window, going back from "now", i.e., verily this moment, for a certain time interval (of w seconds), you still need to define the speed and accuracy with which this check has to be performed. Drools does not have a continually updated notion of "now" in its absolute sense. It is possible to create and maintain a fact representing an approximation of "now", using a timer (which is preferable to using a listener). The Now-fact has to be updated periodically, every d seconds. If you insert a new event with a time stamp after the last update of Now, it will not be recognized for up to d seconds. (And if you insert a new event with a time stamp between w and w + d seconds in the past, it is possible that it triggers the rule.)

Since you haven't indicated how you insert events and how their time stamps are implemented I cannot provide rules illustrating what I have outlined. See the Drools documentation about "Timers and Calendars".

Edit

What has not been said in the question is the relation of an event's time (i.e., when it really happened in the real world) and its timestamp (i.e., when it was entered into Working Memory). Rules checking for an events timestamp being in the last week or month or second are futile: this will be invariably true.

If you call fireAllRules repeatedly, updating the time horizon with a timestamp 1 week (month,...) back before the call is one simple way. Or update Now before each call. Both is far from "hacky".



来源:https://stackoverflow.com/questions/34563843/drools-time-based-constraints-and-now

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!