Search in sources :

Example 1 with TaskDataEvent

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);
    }
}
Also used : TaskDataEvent(org.kie.kogito.taskassigning.service.event.TaskDataEvent) TaskAssigningSolution(org.kie.kogito.taskassigning.core.model.TaskAssigningSolution) UserDataEvent(org.kie.kogito.taskassigning.service.event.UserDataEvent) AssignTaskProblemFactChange(org.kie.kogito.taskassigning.core.model.solver.realtime.AssignTaskProblemFactChange) ProblemFactChange(org.optaplanner.core.api.solver.ProblemFactChange) SolutionUpdatedOnBackgroundDataEvent(org.kie.kogito.taskassigning.service.event.SolutionUpdatedOnBackgroundDataEvent)

Example 2 with TaskDataEvent

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);
    }
}
Also used : TaskDataEvent(org.kie.kogito.taskassigning.service.event.TaskDataEvent) TaskAssigningSolution(org.kie.kogito.taskassigning.core.model.TaskAssigningSolution) TaskAssignment(org.kie.kogito.taskassigning.core.model.TaskAssignment)

Example 3 with TaskDataEvent

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;
}
Also used : TaskDataEvent(org.kie.kogito.taskassigning.service.event.TaskDataEvent) ArrayList(java.util.ArrayList)

Example 4 with TaskDataEvent

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());
}
Also used : TaskDataEvent(org.kie.kogito.taskassigning.service.event.TaskDataEvent) TaskDataEvent(org.kie.kogito.taskassigning.service.event.TaskDataEvent) DataEvent(org.kie.kogito.taskassigning.service.event.DataEvent) UserDataEvent(org.kie.kogito.taskassigning.service.event.UserDataEvent) SolutionUpdatedOnBackgroundDataEvent(org.kie.kogito.taskassigning.service.event.SolutionUpdatedOnBackgroundDataEvent) TaskAssigningServiceContext(org.kie.kogito.taskassigning.service.TaskAssigningServiceContext) Test(org.junit.jupiter.api.Test)

Example 5 with TaskDataEvent

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);
}
Also used : TaskDataEvent(org.kie.kogito.taskassigning.service.event.TaskDataEvent) TaskData(org.kie.kogito.taskassigning.service.TaskData) Test(org.junit.jupiter.api.Test)

Aggregations

TaskDataEvent (org.kie.kogito.taskassigning.service.event.TaskDataEvent)8 SolutionUpdatedOnBackgroundDataEvent (org.kie.kogito.taskassigning.service.event.SolutionUpdatedOnBackgroundDataEvent)3 UserDataEvent (org.kie.kogito.taskassigning.service.event.UserDataEvent)3 Test (org.junit.jupiter.api.Test)2 TaskAssigningSolution (org.kie.kogito.taskassigning.core.model.TaskAssigningSolution)2 AssignTaskProblemFactChange (org.kie.kogito.taskassigning.core.model.solver.realtime.AssignTaskProblemFactChange)2 TaskData (org.kie.kogito.taskassigning.service.TaskData)2 DataEvent (org.kie.kogito.taskassigning.service.event.DataEvent)2 ProblemFactChange (org.optaplanner.core.api.solver.ProblemFactChange)2 ArrayList (java.util.ArrayList)1 TaskAssignment (org.kie.kogito.taskassigning.core.model.TaskAssignment)1 TaskAssigningServiceContext (org.kie.kogito.taskassigning.service.TaskAssigningServiceContext)1 TestUtil.mockTaskData (org.kie.kogito.taskassigning.service.TestUtil.mockTaskData)1