use of org.kie.kogito.taskassigning.service.event.TaskDataEvent in project kogito-apps by kiegroup.
the class TaskAssigningService method processDataEvents.
/**
* Invoked when a set of events are received for processing.
* Three main scenarios might happen:
* a) A solution already exists and thus the proper problem fact changes are calculated and passed to the solver for
* execution. If there are no changes to apply, wait for more events.
*
* b) No solution exists. Instruct the solution data loader to read the users information and the solver will be
* started when this information is returned plus the information collected from the events.
*
* c) A solution improved on background event arrives and must be processed accordingly.
*
* @param events a list of events to process.
*/
synchronized void processDataEvents(List<DataEvent<?>> events) {
if (isNotOperative()) {
LOGGER.warn(SERVICE_INOPERATIVE_MESSAGE, context.getStatus());
return;
}
try {
List<TaskDataEvent> newTaskDataEvents = filterNewestTaskEventsInContext(context, events);
if (currentSolution.get() == null) {
List<TaskDataEvent> activeTaskEvents = newTaskDataEvents.stream().filter(IS_ACTIVE_TASK_EVENT).collect(Collectors.toList());
if (!activeTaskEvents.isEmpty()) {
// b) no solution exists, store the events and get the users from the external user service.
startingEvents = activeTaskEvents;
startingFromEvents.set(true);
loadSolutionData(false, true, config.getDataLoaderPageSize());
} else {
resumeEvents();
}
} else {
// a) a solution exists, calculate and apply the potential changes if any.
UserDataEvent userDataEvent = filterNewestUserEvent(events);
List<ProblemFactChange<TaskAssigningSolution>> changes = SolutionChangesBuilder.create().forSolution(currentSolution.get()).withContext(context).withUserServiceConnector(userServiceConnectorDelegate).withProcessors(processorRegistry).fromTasksData(fromTaskDataEvents(newTaskDataEvents)).fromUserDataEvent(userDataEvent).build();
if (!changes.isEmpty()) {
LOGGER.debug("processDataEvents - there are changes: {} to apply", changes.size());
cancelScheduledImproveSolutionOnBackgroundTimer();
solverExecutor.addProblemFactChanges(changes);
} else {
// c) check if an event for the improve solution on background period has arrived and a better
// solution was produced
SolutionUpdatedOnBackgroundDataEvent solutionImprovedOnBackgroundEvent = filterNewestSolutionUpdatedOnBackgroundEvent(events);
TaskAssigningSolution currentLastBestSolution = lastBestSolution.get();
if (solutionImprovedOnBackgroundEvent != null && hasToApplyImprovedOnBackgroundSolution(solutionImprovedOnBackgroundEvent, currentLastBestSolution)) {
// a better solution was produced during the improveSolutionOnBackgroundDuration period
LOGGER.debug("processDataEvents - apply the improved on background solution: {}", currentLastBestSolution);
executeSolutionChange(currentLastBestSolution);
} else {
executePlanOrResumeEvents(currentSolution.get());
}
}
}
} catch (Exception e) {
failFast(e);
}
}
use of org.kie.kogito.taskassigning.service.event.TaskDataEvent in project kogito-apps by kiegroup.
the class TaskAssigningService method onSolutionDataLoad.
/**
* Invoked by the SolutionDataLoader when the data for initializing the solution has been loaded successfully.
* Two main scenarios might happen:
* a) The service is starting and thus the initial solution load is attempted. If there are available tasks, the
* solver will be started, first solution will arrive, etc.
*
* b) No tasks where available at the time of service initialization and thus no solution to start the solver.
* At a later point in time events arrived and the solution can be started with the information coming for them plus
* the user information loaded by the solution data loader.
*
* @param result contains the requested data for creating the initial solution.
*/
synchronized void onSolutionDataLoad(SolutionDataLoader.Result result) {
if (isNotOperative()) {
LOGGER.warn(SERVICE_INOPERATIVE_MESSAGE, context.getStatus());
return;
}
try {
LOGGER.debug("Solution data loading has finished, startingFromEvents: {}, includeTasks: {}" + ", includeUsers: {}, tasks: {}, users: {}", startingFromEvents, !startingFromEvents.get(), true, result.getTasks().size(), result.getUsers().size());
context.setStatus(ServiceStatus.READY);
TaskAssigningSolution solution;
List<TaskAssignment> taskAssignments;
if (startingFromEvents.get()) {
// data loader has responded with the users.
if (hasQueuedEvents()) {
// incorporate the events that could have been arrived in the middle while the users were being loaded.
List<TaskDataEvent> newEvents = filterNewestTaskEventsInContext(context, pollEvents());
startingEvents = combineAndFilerNewestActiveTaskEvents(startingEvents, newEvents);
}
solution = SolutionBuilder.newBuilder().withTasks(fromTaskDataEvents(startingEvents)).withUsers(result.getUsers()).withProcessors(processorRegistry).build();
startingFromEvents.set(false);
startingEvents = null;
} else {
// a) normal initialization procedure after getting the tasks and users from the solution data loader
solution = SolutionBuilder.newBuilder().withTasks(result.getTasks()).withUsers(result.getUsers()).withProcessors(processorRegistry).build();
}
// if the solution has non dummy tasks the solver can be started.
taskAssignments = filterNonDummyAssignments(solution.getTaskAssignmentList());
if (!taskAssignments.isEmpty()) {
taskAssignments.forEach(taskAssignment -> {
context.setTaskPublished(taskAssignment.getId(), taskAssignment.isPinned());
context.setTaskLastEventTime(taskAssignment.getId(), taskAssignment.getTask().getLastUpdate());
});
solverExecutor.start(solution);
userServiceAdapter.start();
} else {
resumeEvents();
}
} catch (Exception e) {
failFast(e);
}
}
use of org.kie.kogito.taskassigning.service.event.TaskDataEvent in project kogito-apps by kiegroup.
the class EventUtil method filterNewestTaskEventsInContext.
/**
* Given a list of events finds the newest event per each task (in case if any) that were never processed in current
* context and adds it to the results list.
* The returned events are automatically marked as processed in the context.
*
* @param context the context instance that holds the processed events information.
* @param dataEvents a list of events to filter.
* @return a list of events were each event is the newest one that could be found for the given task that was never
* processed in the current context before.
*/
public static List<TaskDataEvent> filterNewestTaskEventsInContext(TaskAssigningServiceContext context, List<DataEvent<?>> dataEvents) {
List<TaskDataEvent> result = new ArrayList<>();
List<TaskDataEvent> newestTaskEvents = filterNewestTaskEvents(dataEvents);
for (TaskDataEvent taskEvent : newestTaskEvents) {
if (context.isNewTaskEventTime(taskEvent.getTaskId(), taskEvent.getEventTime())) {
context.setTaskLastEventTime(taskEvent.getTaskId(), taskEvent.getEventTime());
result.add(taskEvent);
}
}
return result;
}
use of org.kie.kogito.taskassigning.service.event.TaskDataEvent in project kogito-apps by kiegroup.
the class EventUtilTest method filterNewestTaskEventsInContext.
@Test
void filterNewestTaskEventsInContext() {
TaskAssigningServiceContext context = new TaskAssigningServiceContext();
context.setTaskLastEventTime(TASK_2, TASK_2_EVENT_1.getEventTime());
context.setTaskLastEventTime(TASK_3, TASK_3_EVENT_2.getEventTime());
context.setTaskLastEventTime(TASK_4, TASK_4_EVENT_3.getEventTime());
List<DataEvent<?>> eventList = buildDataEvents();
List<TaskDataEvent> result = EventUtil.filterNewestTaskEventsInContext(context, eventList);
assertThat(result).hasSize(3).contains(TASK_1_EVENT_3, TASK_2_EVENT_3, TASK_3_EVENT_3);
assertThat(context.getTaskLastEventTime(TASK_1)).isEqualTo(TASK_1_EVENT_3.getEventTime());
assertThat(context.getTaskLastEventTime(TASK_2)).isEqualTo(TASK_2_EVENT_3.getEventTime());
assertThat(context.getTaskLastEventTime(TASK_3)).isEqualTo(TASK_3_EVENT_3.getEventTime());
assertThat(context.getTaskLastEventTime(TASK_4)).isEqualTo(TASK_4_EVENT_3.getEventTime());
}
use of org.kie.kogito.taskassigning.service.event.TaskDataEvent in project kogito-apps by kiegroup.
the class TaskUtilTest method fromTaskDataEvents.
@Test
void fromTaskDataEvents() {
TaskData taskData1 = mock(TaskData.class);
TaskData taskData2 = mock(TaskData.class);
List<TaskData> result = TaskUtil.fromTaskDataEvents(Arrays.asList(new TaskDataEvent(taskData1), new TaskDataEvent(taskData2)));
assertThat(result).containsExactly(taskData1, taskData2);
}
Aggregations