Drools Stream 模式负模式

Drools Stream mode negative patterns

我对 Drools 中的流模式有疑问。 我正在使用这条规则

declare MetaMessage
        @role(event)
end
 
rule 'rule1' ruleflow-group 'default'  
    when  
        $inMess : MetaMessage() from entry-point 'default'
        not(MetaMessage(this != $inMess, this after [0s,10s] $inMess) from entry-point 'default')
    then  
        //do things
end

如果我发送 MetaMessage,我希望规则在指定的 10 秒后执行,但没有任何反应。 如果我发送一个新的 MetaMessage,10 秒后,规则就会执行。

编辑:如果我更改规则并去掉 not,效果会很好

我不确定我做错了什么。

这就是我创建 KieBase 的方式

KieBaseConfiguration config = KieServices.Factory.get().newKieBaseConfiguration();
config.setOption(EventProcessingOption.STREAM);
KieBase kieBase = kieHelper.build(config);
KieSession kieSession = kieBase.newKieSession();

编辑 2 每次在 Kafka 队列中插入新的 MetaMessage 时,我都会使用 fireAllRules() 触发规则。 所以我有一个消费者收集消息并将它们插入会话中,就像这样

EntryPoint ep = kieSession.getEntryPoint("default");
ep.insert(metaMessage);
kieSession.fireAllRules();

编辑 3 我有另一个简单的规则与前一个一起执行

rule "AccumulatedTest"

    when
        accumulate(MetaMessage( timestamp > 0 ); $cnt: count(1))
    then
        log.info("Message n: "+$cnt);
end

第一次插入消息时(当新创建 kieSession 时)我得到信息“Message n: 0”。 但是此规则不再触发。

如果在会话中插入任何其他消息,则不会触发规则

您使用 ruleflow-group 'default',因此您必须将焦点设置到议程组才能执行规则,例如 getSession().getAgenda().getAgendaGroup("default").setFocus();

您很可能在事件插入之前或之后设置了焦点。插入第一条消息后,您设置了焦点,但当时没有规则被添加到议程(规则还没有资格执行),并且焦点被重置到主议程组。 10 秒后,您声明尽管该规则已添加到 'default' 议程,但没有触发任何规则(因为主要组有焦点)。您插入第二条消息并将焦点设置到 'default' 议程,该议程从第一条消息触发的议程中执行规则。

如果您

,规则将被执行
  1. 删除ruleflow-group(最新文档提升agenda-group
  2. auto-focus true添加到规则
  3. 10 秒后设置议程组焦点

how agenda group works

好的,感谢@EstebanAliverti 和@Mike,我已经解决了这个问题。

让我详细说明:

  • 我必须创建一个计划的 fireAllRules() 每 1 秒运行一次(正如@EstebanAliverti 建议的那样)
  • 我从规则中删除了 ruleflow-group,因为(正如@Mike 建议的那样)焦点切换回默认议程组,并且在我的实施中,我无法从计划执行中传递议程组

现在 fireAllRules() 每 1 秒运行一次,没有规则流或议程组

现在规则看起来像这样并且按预期工作

declare MetaMessage
        @role(event)
end
 
rule 'rule1'
    when  
        $inMess : MetaMessage() 
        not(MetaMessage(this != $inMess, this after [0s,10s] $inMess) )
    then  
        //do things
end

最后但同样重要的是,由于我删除了入口点,因为我没有使用该功能,所以我现在将消息直接插入 KieSession

kieSession.insert(metaMessage);
kieSession.fireAllRules();