drools - Drools Fusion CEP 中的测试事件到期

标签 drools complex-event-processing drools-fusion

Ciao,我已经通过多种方式进行了测试,但我仍然无法测试和验证 Drools Fusion 中的事件过期机制,所以我正在寻找一些小指导,好吗?

我已阅读手册并且对此功能感兴趣:

In other words, one an event is inserted into the working memory, it is possible for the engine to find out when an event can no longer match other facts and automatically retract it, releasing its associated resources.

我在 Eclipse 5.4.0.Final 中使用 Drools IDE,并修改了“新建 Drools 项目”向导创建的模板代码来测试和验证事件过期。

下面的代码。我理解的让“生命周期”正常工作的方法是:

  • 您必须在 STREAM 模式下设置 KBase - 检查
  • 您必须按时间顺序插入事件 - 检查
  • 您必须定义事件之间的时间约束 - 在我的情况下检查是最后一个 Message()

但是,当我最后检查 EventFactHandle 时,没有任何 Event() 已过期。 感谢您的帮助。

Java:

public class DroolsTest {

    public static final void main(String[] args) {
        try {
            KnowledgeBase kbase = readKnowledgeBase();
            // I do want the pseudo clock
            KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
            conf.setOption(ClockTypeOption.get("pseudo"));
            StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(conf, null);
            SessionPseudoClock clock = ksession.getSessionClock();
            KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
            // Insert of 2 Event:
            Message message = new Message();
            message.setMessage("Message 1");
            message.setStatus(Message.HELLO);
            ksession.insert(message);
            ksession.fireAllRules();
            clock.advanceTime(1, TimeUnit.DAYS);
            Message message2 = new Message();
            message2.setMessage("Message 2");
            message2.setStatus(Message.HELLO);
            ksession.insert(message2);
            ksession.fireAllRules();
            clock.advanceTime(1, TimeUnit.DAYS);
            ksession.fireAllRules();
            // Now I do check what I have in the working memory and if EventFactHandle if it's expired or not:
            for (FactHandle f : ksession.getFactHandles()) {
                if (f instanceof EventFactHandle) {
                    System.out.println(((EventFactHandle)f)+" "+((EventFactHandle)f).isExpired());
                } else {
                    System.out.println("not an Event: "+f);
                }
            }
            logger.close();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        if (errors.size() > 0) {
            for (KnowledgeBuilderError error: errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        // following 2 lines is the template code modified for STREAM configuration
        KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
        config.setOption( EventProcessingOption.STREAM );
        return kbase;
    }

    /*
     * This is OK from template, as from the doc:
     * By default, the timestamp for a given event is read from the Session Clock and assigned to the event at the time the event is inserted into the working memory.
     */
    public static class Message {

        public static final int HELLO = 0;
        public static final int GOODBYE = 1;

        private String message;

        private int status;

        public String getMessage() {
            return this.message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public int getStatus() {
            return this.status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

    }

}

流口水:

package com.sample

import com.sample.DroolsTest.Message;

declare Message
@role(event)
end

declare window LastMessageWindow
    Message() over window:length(1)
end

rule "Hello World"
    when
       accumulate( $m : Message(status==Message.HELLO) from window LastMessageWindow,
                $messages : collectList( $m ) )
    then
        System.out.println( ((Message)$messages.get(0)).getMessage() );
end

请注意:即使我在消息事件中添加 1 秒的过期时间,通过

@expires(1s)

我仍然没有得到预期的结果,即插入的第一个消息事件,我本来预期现在已过期?感谢您的帮助。

最佳答案

找到解决办法了!显然,我很愚蠢,没有意识到我正在使用 Drools 5.4.0.Final,同时仍然引用 5.2.0.Final 的旧文档。在 Drools Fusion 5.4.0.Final 的更新文档中,为 2.6.2 添加了此框。滑动长度窗口:

Please note that length based windows do not define temporal constraints for event expiration from the session, and the engine will not consider them. If events have no other rules defining temporal constraints and no explicit expiration policy, the engine will keep them in the session indefinitely.

因此,我最初提出的第三个要求“您必须定义事件之间的时间约束”显然没有得到满足,因为我现在了解了 Drools 5.4.0.Final 中的滑动长度窗口:

Message() over window:length(1)

确实不是 session 中事件到期的时间约束的定义。

更新此答案希望有人会发现它有帮助。另外,正如您所知,我实际上很愚蠢,因为依靠谷歌搜索才能找到文档,有时您不会被重定向到当前的发行文档,所以看起来...

关于drools - Drools Fusion CEP 中的测试事件到期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12338385/

相关文章:

rest - Apache Camel 和 Drools 融合集成

java - Drools Fusion 不支持从 java.time.ZonedDateTime 转换为 long

spring - 如何在 Drools 规则中使用 Spring 服务?

drools - 无法创建构造函数::Kie Workbench

java - Esper:注意,当事件数量(具有特定参数)超过阈值时

architecture - 扩展 StreamInsight 的方法?

java - Drools Fusion 支持持久的、长时间运行的事件

java - 如何为外部存储序列化 JBoss Drools KieBase 集合?

Drools - 使用累加找到最小值和最大值

java - 如何在 Drools 5.6 规则中定义常量集合