2

I am trying to set KieSession date to same date with the date variable in my object before running the rules. I use this configuration to create my KieSession

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

Before running the rules I use advanceTime() to set the date of the session to desired date.

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

This resulted misfires in the rules that uses sliding windows. Lets say checking the objects that passed in 1 hour and I don't have any in the last hour. I only have 3 objects day before. Here is an example dataset of objects.

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

I have a rule which checks if there are more than 2 objects with the same clientId over 1 hour.

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

When I pass an object with these values. The rule above returns true but we clearly don't have any objects that has a date within last hour.

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

I believe this is broken because of the new configuration as it was working previously (when I did not try to change session clock) but I want session date to be equal to object date. Anyone has ideas what is the problem here and how to fix it?

Dogukan Evcil
  • 313
  • 4
  • 15
  • 2
    How are you incrementing the psuedo clock between calls to simulate the passage of time between events? – Roddy of the Frozen Peas Feb 10 '21 at 20:54
  • I understand that I have to adjust session clock for every timestamped event, and I cannot do it with newInsertElements of CommandFactory. Should I do it before or after inserting each event? – Dogukan Evcil Feb 11 '21 at 07:35

1 Answers1

2

As Roddy of the Frozen Peas made the remark, you need to manipulate SessionPseudoClock in between every insert of your events. I'd implement a new Command, extend InsertElementsCommand and @Override it's execute method:

    @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;
    }

and instead of:

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

I'd:

commands.add(new YourInsertElementsCommand(objects));

Hasan Can Saral
  • 2,950
  • 5
  • 43
  • 78