Drools Fusion SessionPseudoClock 未按预期工作

问题描述

在运行规则之前,我试图将 KieSession 日期设置为与对象中的日期变量相同的日期。我使用此配置来创建我的 KieSession

KieSessionConfiguration configuration = KieServices.Factory.get().newKieSessionConfiguration();
configuration.setoption(ClockTypeOption.get("pseudo"));

在运行规则之前,我使用 advanceTime() 将会话日期设置为所需日期。

final SessionPseudoClock clock = kSession.getSessionClock();
clock.advanceTime(object.getDate().getTime() - System.currentTimeMillis(),TimeUnit.MILLISECONDS);

final List<Command<?>> commands = new ArrayList<>();

commands.add(CommandFactory.newInsertElements(objects)
commands.add(CommandFactory.newInsert(object,"object"));

final ExecutionResults results = kSession.execute(CommandFactory.newBatchExecution(commands));

这导致使用滑动窗口的规则失火。假设检查 1 小时内通过的对象,而我在过去一小时内没有任何对象。我前一天只有 3 个对象。这是对象的示例数据集。

objects: [
  {
    clientId: "id",date: 2021-02-09T12:00:38.249Z,...
  }
  {
    clientId: "id",date: 2021-02-09T13:00:38.249Z,date: 2021-02-09T14:00:38.249Z,...
  }
]

我有一个规则,用于检查在 1 小时内是否有 2 个以上的对象具有相同的 clientId

$object : Object($clientId : clientId)
List( size > 2 ) from collect ( Object( this before $object,clientId == $clientId ) over window:time(1h))

当我传递具有这些值的对象时。上面的规则返回 true,但我们显然没有任何对象在过去一小时内具有日期。

  { clientId: "id",date: 2021-02-10T14:00:38.249Z,... }

我相信这是由于新配置而被破坏,因为它以前在工作(当我没有尝试更改会话时钟时),但我希望会话日期等于对象日期。任何人都知道这里的问题是什么以及如何解决它?

解决方法

正如 Roddy of the Frozen Peas 所说,您需要在每次插入事件之间操作 SessionPseudoClock。我会实现一个新的 Command,扩展 InsertElementsCommand@Override 它是 execute 方法:

    @Override
    public Collection<FactHandle> execute(Context context) {

        KieSession kSession = ((RegistryContext) context).lookup(KieSession.class);
        List<FactHandle> handles = new ArrayList<>();

        Object workingMemory = StringUtils.isEmpty(super.getEntryPoint()) ?
                kSession :
                kSession.getEntryPoint(super.getEntryPoint());

        SessionPseudoClock clock = kSession.getSessionClock();

        super.objects.forEach(event -> {
            clock.advanceTime(((YourObject) event).getDate().getTime() - clock.getCurrentTime(),TimeUnit.MILLISECONDS);
            handles.add(((EntryPoint) workingMemory).insert(event));
        });

        ...

        return handles;
    }

而不是:

commands.add(CommandFactory.newInsertElements(objects));

我会:

commands.add(new YourInsertElementsCommand(objects));

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...