【问题标题】:Drools Fusion SessionPseudoClock Not working as expectedDrools Fusion SessionPseudoClock 未按预期工作
【发布时间】:2021-02-10 10:41:30
【问题描述】:

在运行规则之前,我正在尝试将 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,
    ...
  }
  {
    clientId: "id",
    date: 2021-02-09T14:00:38.249Z,
    ...
  }
]

我有一个规则检查是否有超过 2 个具有相同 clientId 的对象超过 1 小时。

$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, ... }

我认为这是由于之前使用的新配置(当我没有尝试更改会话时钟时)而导致的,但我希望会话日期等于对象日期。任何人都知道这里的问题是什么以及如何解决它?

【问题讨论】:

  • 如何在调用之间增加伪时钟以模拟事件之间的时间流逝?
  • 我知道我必须为每个带时间戳的事件调整会话时钟,而我无法使用 CommandFactory 的 newInsertElements 来做到这一点。我应该在插入每个事件之前还是之后这样做?

标签: drools kie drools-fusion


【解决方案1】:

正如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));

【讨论】:

    猜你喜欢
    • 2020-08-12
    • 2021-06-04
    • 2022-01-24
    • 2015-05-11
    • 2020-05-15
    • 2014-10-31
    • 2018-02-12
    • 2014-01-20
    • 2015-01-13
    相关资源
    最近更新 更多