0

我无法理解 JBoss Drools 推理引擎如何与复杂的事件处理(drools fusion)一起工作。实际上,如果在 5 秒内发生超过 2 个交易,我创建了一个规则来拒绝交易。这是规则

rule "more than 2 transaction in 5 seconds"
  when
    $transaction : Transaction( $id : id )
    Number(intValue > 2) from accumulate(
        $t : Transaction() over window:time(5s),
        count($t))

then
   $transaction.setDenied(true);
end

我使用伪会话时钟将会话设置为流模式。这里是java代码

SessionPseudoClock clock = kSession.getSessionClock();
Transaction tx1 = new Transaction(new BigInteger("10000"), TransactionType.CREDIT_CARD, 1L);
Transaction tx2 = new Transaction(new BigInteger("2000"), TransactionType.CREDIT_CARD,2L);
Transaction tx3 = new Transaction(new BigInteger("50000"), TransactionType.DEPOSIT,3L);
Transaction tx4 = new Transaction(new BigInteger("100"), TransactionType.WITHDRAW,4L);

assertTransaction(kSession, tx1);

clock.advanceTime(6, TimeUnit.SECONDS);
assertTransaction(kSession, tx2);

clock.advanceTime(3, TimeUnit.SECONDS);
assertTransaction(kSession, tx3);

clock.advanceTime(1800, TimeUnit.MILLISECONDS);
assertTransaction(kSession, tx4);

其中 assertTransaction simple 包含以下代码:

kSession.insert(tx);
kSession.fireAllRules();

触发规则匹配的事务是 tx4,因为 tx2 在 tx1 和 tx1 退出定时窗口后 6 秒发生。奇怪的是,规则的动作是针对工作内存中的所有事务执行的,即使是 tx1。

它应该以这种方式工作吗?

提前致谢

4

1 回答 1

0

主要问题是引擎没有机会执行挂起的激活并根据(伪)时钟的当前读数处理事实。此外,该规则将为当前在工作内存中的每个事务触发,而您希望它仅针对最新事务触发。

对于 CEP、测试或生产,我建议在单独的线程中运行引擎,调用 fireUntilHalt。然后,对于测试或生产,可以使用真实时钟并在事实来自或来自插入之间暂停的线程时插入事实。并且也可以使用伪时钟,几乎不需要对代码进行任何更改。

要确保规则仅对最近的线程触发,请将规则更改为

rule "more than 2 transaction in 5 seconds"
when
    $transaction : Transaction( $id : id )
    not Transaction( this after $transaction )
    Number(intValue > 2) from accumulate(
        $t : Transaction() over window:time(5s),
        count($t))
then
    System.out.println( "denied: " + $transaction );
end
于 2015-08-17T13:32:36.387 回答