【问题标题】:Drools accumulate is updating an irrelevant fact流口水的积累正在更新一个无关紧要的事实
【发布时间】:2020-10-23 14:16:36
【问题描述】:

在 Drools 中使用累积时,会针对未更新的事实评估和触发规则。

规则如下:

rule "WidgetsPerUser"
    when
        $user : User()
        accumulate(
            Widget ( checkIsUser($user) ); 
            $widgetCount : sum(1)
        )
    then
        System.out.println($user + " has " +  $widgetCount + " widgets");
end

这个想法很简单:计算每个UserWidget 对象的数量。 checkIsUser() 是一个简单的相等性检查,但表示不能使用索引的检查。

这是 Drools 7.0.0.Final 的示例输出:

-- Calling fire all rules --
User5 has 10 widgets
User4 has 10 widgets
User3 has 10 widgets
User2 has 10 widgets
User1 has 10 widgets

Widget moved from User3 to User1

-- Calling fire all rules --
User5 has 10 widgets
User3 has 9 widgets
User1 has 11 widgets

这里我们有 5 个User 事实插入到内存中,并且所有Widget 的起始计数都是 10。fireAllRules 的第一次调用显示正确的打印,因为所有User 事实都插入到内存中。接下来是更新,其中 Widget 从 User3 移动到 User1。存在预期的输出,但是 User5 没有理由显示为正在更新。

要直观地突出问题:

User5 has 10 widgets    (User5 should NOT be triggered!)

                        (User4 is correctly ignored)

User3 has 9 widgets     (User3 is correctly triggered)

                        (User2 is correctly ignored)

User1 has 11 widgets    (User1 is correctly triggered)

User5 与 User2 或 User4 的唯一不同之处在于它是最后添加的用户事实,那么为什么它的行为会有所不同呢?

是否需要额外的评估?它有什么用途?

请注意,问题不在于如何避免或解决额外的触发器。

【问题讨论】:

    标签: drools


    【解决方案1】:

    我自己在流口水核心周围挖掘以获得一些答案。我发现了以下内容(在 7.0.0 和 7.39.0 两个版本中):

    在评估累加节点 PhreakAccumulateNode.doRightUpdates 更新的方法中,就在方法 doRightUpdatesProcessChildren(用于匹配左右元组)之前,存在以下代码:

    // if LeftTupleMemory is empty, there are no matches to modify
    if ( leftTuple != null ) {
       if ( leftTuple.getStagedType() == LeftTuple.NONE ) {
             trgLeftTuples.addUpdate( leftTuple ); //<----
       }
       doRightUpdatesProcessChildren( ARGS );
    }
    

    基于此,无论内存中的元组中是否存在匹配项,如果作为累加器的一部分的事实有更新,则第一个左元组(在本例中为 User5)将始终被视为正在匹配中。

    我查看了另一个 beta 节点 JoinNode。该节点的代码类似于AccumulateNode,但是它缺少第一个左元组的额外更新,导致我相信它是意外添加的,没有理由存在。

    我说得对吗?

    【讨论】:

    • 您的分析是 100% 正确的。我在issues.redhat.com/browse/DROOLS-5488 报告了这个问题,并按照你的建议发送了一个修复它的请求github.com/kiegroup/drools/pull/2978 该修复将从 Drools 7.41 获得。如果您以后会发现类似的问题,请随时在我们的 jira 上开票。非常感谢!
    • 谢谢,很高兴能帮上忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多