首页 文章

Drools Fusion CEP中的测试事件到期

提问于
浏览
2

Ciao,我已经在几个方面进行了测试,但我还是无法测试和验证Drools Fusion中的事件到期机制,所以我正在寻找一些小指导,好吗?

我已阅读本手册,我对此功能感兴趣:

换句话说,一个事件被插入到工作存储器中,引擎可以找出事件何时不能与其他事实匹配并自动收回它,释放其相关资源 .

我正在使用Eclipse中的Drools IDE,5.4.0.Final,我修改了“New Drools Project”向导创建的模板代码,以测试和验证Event expiration .

下面的代码 . 我理解为使“生命周期”正常工作的方式是:

  • 您必须在STREAM模式下设置KBase - 检查

  • 您必须按时间顺序插入事件 - 检查

  • 您必须在事件之间定义时间约束 - 在我的情况下检查是最后一条消息()

但是,当我在最后检查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;
        }

    }

}

Drools的:

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

请注意:即使我在Message事件中添加1秒的到期时间,依据

@expires(1s)

我仍然没有得到插入第一个Message事件的预期结果,我原以为现在已经过期了?谢谢你的帮助 .

1 回答

  • 3

    找到解决方案显然,我是愚蠢的,并没有意识到我正在使用Drools 5.4.0.Final,同时仍然指的是5.2.0.Final的旧文档 . 在Drools Fusion 5.4.0.Final的更新文档中,为 2.6.2. Sliding Length Windows 添加了此框:

    请注意,基于长度的窗口没有为会话中的事件过期定义时间约束,引擎将不会考虑它们 . 如果事件没有定义时间约束的其他规则且没有明确的到期策略,则引擎将无限期地将它们保留在会话中 .

    因此,我最初申请的“你必须在事件之间定义时间约束”的第三个要求显然是不符合的,因为我现在理解Drools 5.4.0中的Sliding Length Window.Final:

    Message() over window:length(1)
    

    确实不是会话中事件过期的时间约束的定义 .

    更新这个答案希望有人会发现它有用 . 另外,为了你的知道,我实际上依靠谷歌搜索来获取文档是愚蠢的,有时候你没有被重定向到当前的发布文档,所以看起来......

相关问题