流口水基于时间的约束和 "now"
drools time based constraints and "now"
我们正在尝试写一个流口水,上面写着类似“如果事件发生在上周,执行后果”之类的话。我们有代表事件发生时间的常规 java 日期对象,但我们不确定如何在流口水的 LHS 中表达我们希望该日期对象发生在上周。重要的是,一周的时间跨度是任意的。它可以随时更改为月份或年份。最后,请记住我们的会话是有状态的。
我在这里发现了一个有点相关的问题:
use java.util.Date in a rule's LHS。我将从下面的答案中引用最相关的摘录:
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).
在回答中,作者描述了“现在”表示的问题。他的解决方案似乎很老套,答案发布在更早版本的 drools 中。我在这里提出一个新问题,以更好地关注这个问题,而不是在我链接的问题中得到的传递处理。
更新:
时间戳是简单的 java.util.Date 对象。
事件通过 api 调用添加到会话中。有状态会话是由 java 基于 api 持有的对象。 api 在提交事件时将事件添加到知识会话中。 FireAllRules 大约每秒发生一次。
基本问题(通常如此)是要求真正的含义。事件 "happening in the last week" 可以是 7*24*60*60 秒前发生的任何事情;它可能是从 20151228 星期一到现在发生的事情,或者从 20151227 星期日到现在发生的事情,或者可能只是日期重要而不是一天中的时间的类似事情。
询问它的真正含义,并相应地改写你的问题。
如果您确实需要滑动 window,从 "now" 返回,也就是说,确实是这一刻,一定时间间隔(w秒),您仍然需要定义必须执行此检查的速度和准确性。 Drools 在绝对意义上没有持续更新的 "now" 概念。 可以创建和维护表示 近似值的事实 的 "now",使用计时器(比使用侦听器更可取)。 Now-fact 必须定期更新,每 d 秒。如果您在 Now 的最后一次更新 之后插入一个带有时间戳 的新事件,它将在长达 d 秒内无法被识别。 (并且如果您在 w 和 w + d 秒之间插入时间戳为过去,有可能触发规则。)
由于您没有说明如何插入事件以及如何实现它们的时间戳,因此我无法提供说明我所概述内容的规则。请参阅有关 "Timers and Calendars".
的 Drools 文档
编辑
问题中没有说的是事件的时间(即它在现实世界中真正发生的时间)与其时间戳之间的关系(即,当它进入工作记忆时)。检查事件 timestamp 是否在上周或一个月或第二秒的规则是徒劳的:这将始终为真。
如果您重复调用 fireAllRules,使用调用前 1 周(月,...)的时间戳更新时间范围是一种简单的方法。或者在每次通话前更新 Now。两者都远 "hacky".
我们正在尝试写一个流口水,上面写着类似“如果事件发生在上周,执行后果”之类的话。我们有代表事件发生时间的常规 java 日期对象,但我们不确定如何在流口水的 LHS 中表达我们希望该日期对象发生在上周。重要的是,一周的时间跨度是任意的。它可以随时更改为月份或年份。最后,请记住我们的会话是有状态的。
我在这里发现了一个有点相关的问题: use java.util.Date in a rule's LHS。我将从下面的答案中引用最相关的摘录:
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).
在回答中,作者描述了“现在”表示的问题。他的解决方案似乎很老套,答案发布在更早版本的 drools 中。我在这里提出一个新问题,以更好地关注这个问题,而不是在我链接的问题中得到的传递处理。
更新:
时间戳是简单的 java.util.Date 对象。
事件通过 api 调用添加到会话中。有状态会话是由 java 基于 api 持有的对象。 api 在提交事件时将事件添加到知识会话中。 FireAllRules 大约每秒发生一次。
基本问题(通常如此)是要求真正的含义。事件 "happening in the last week" 可以是 7*24*60*60 秒前发生的任何事情;它可能是从 20151228 星期一到现在发生的事情,或者从 20151227 星期日到现在发生的事情,或者可能只是日期重要而不是一天中的时间的类似事情。
询问它的真正含义,并相应地改写你的问题。
如果您确实需要滑动 window,从 "now" 返回,也就是说,确实是这一刻,一定时间间隔(w秒),您仍然需要定义必须执行此检查的速度和准确性。 Drools 在绝对意义上没有持续更新的 "now" 概念。 可以创建和维护表示 近似值的事实 的 "now",使用计时器(比使用侦听器更可取)。 Now-fact 必须定期更新,每 d 秒。如果您在 Now 的最后一次更新 之后插入一个带有时间戳 的新事件,它将在长达 d 秒内无法被识别。 (并且如果您在 w 和 w + d 秒之间插入时间戳为过去,有可能触发规则。)
由于您没有说明如何插入事件以及如何实现它们的时间戳,因此我无法提供说明我所概述内容的规则。请参阅有关 "Timers and Calendars".
的 Drools 文档编辑
问题中没有说的是事件的时间(即它在现实世界中真正发生的时间)与其时间戳之间的关系(即,当它进入工作记忆时)。检查事件 timestamp 是否在上周或一个月或第二秒的规则是徒劳的:这将始终为真。
如果您重复调用 fireAllRules,使用调用前 1 周(月,...)的时间戳更新时间范围是一种简单的方法。或者在每次通话前更新 Now。两者都远 "hacky".