【问题标题】:Function in "when clause" seems to get cached“when 子句”中的函数似乎被缓存了
【发布时间】:2023-04-02 22:28:01
【问题描述】:

我有一个用例,我需要实现一个计数器,它基本上每分钟重置一次。它在一个名为 Counter 的 java 类中,我在其中使用了两种方法:

  • addDate() 将日期添加到列表中
  • getSize() 清除所有超过一分钟的日期并返回新列表的大小

现在 addDate() 用于我的“then”子句,我在其中进行一些处理,而 getSize() 用于“when”子句。重点是,如果我在最后一分钟已经进行了 N 次治疗,我就不应该进行治疗。

规则如下所示:

rule "AffWebService"
when
    $compteur : Counter(getSize() < max.intValue())
then
    // treatment
    modify ( $compteur ) { addDate() };

结束

基本上它一直有效,直到列表的大小等于 max(这是一个 Drools 全局)。我在 getSize() 函数中添加了一个每次都会触发的记录器,这很好。

现在,棘手的部分。一旦列表的大小等于最大值, getSize() 甚至不再被触发(这是有问题的,因为它与清除“旧日期”的函数相同)。就像 Drools “缓存”了值并且不执行它,也许直到我修改了 Counter ?

顺便说一句,计数器是我在会话开始时仅触发一次的规则中插入的事实。

任何提示表示赞赏...谢谢!

【问题讨论】:

  • 您发布的规则将快速将项目添加到列表中,直到通过一次又一次地立即触发达到最大值。我看不出这应该达到什么目的。也许您告诉我们真正应该发生什么,从哪里添加新项目,何时、如何以及为什么。
  • 嗯,基本上我需要调用一个 Web 服务,而 drools 应该可以帮助我们“不超载”远程服务器。我需要做的是调节流量,例如一分钟不超过 50 个电话。事实是由基于 Java 的应用服务器添加的,所以基本上每次有新的事实进来时,我都需要检查我在最后一分钟是否已经进行了 50 次调用,如果没有,它可以得到处理。 getSize() 会清除最后一分钟以上的日期,以确保更新计数器。
  • 基本上经过更多测试后,一旦条件为 FALSE 一次,规则就不会再次触发,即使 getSize() 返回的值在一段时间后会有所不同。 Fwiw 我使用相同的会话并在触发所有规则后撤回所有事实(但我的计数器)。有什么线索吗?
  • 我尝试添加一个在计数器达到最大值时更新计数器的规则。要么它一遍又一遍地循环,或者如果我添加了无循环,它只会触发一次并且永远不会再触发。有没有办法在每次将新事实添加到工作记忆时触发规则,无论该事实的类型是什么?

标签: java drools rule


【解决方案1】:

我相信你问题中的第二个要点,你说:

getSize() 清除所有超过一分钟的日期并返回新列表的大小

清楚地突出警告/反模式as mentioned in the Drools docs

属性访问器不得以可能影响规则的方式更改对象的状态。请记住,规则引擎会在两次调用之间有效地缓存其匹配结果以使其更快。

所以我的建议是重构 Counter 和规则定义,以避免这个问题并遵守文档;例如,有另一个单独的规则来触发“旧日期”删除和修改计数器,或修改专用计数器“大小”字段 - 两者都在此类的 RHS单独的规则。

(我假设 Drools 版本为 6.4.0.Final)

【讨论】:

    猜你喜欢
    • 2017-11-03
    • 1970-01-01
    • 2012-08-24
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多