use of org.kie.kogito.taskassigning.core.model.User in project kogito-apps by kiegroup.
the class SolutionChangesBuilderTest method addDisableUserChange.
@Test
void addDisableUserChange() {
User user = mockUser(USER_1);
user.setEnabled(true);
TaskAssigningSolution solution = mockSolution(Collections.singletonList(user), Collections.emptyList());
UserDataEvent event = new UserDataEvent(Collections.emptyList(), ZonedDateTime.now());
List<ProblemFactChange<TaskAssigningSolution>> result = SolutionChangesBuilder.create().withContext(context).withUserServiceConnector(userServiceConnector).withProcessors(processorRegistry).fromTasksData(Collections.emptyList()).fromUserDataEvent(event).forSolution(solution).build();
DisableUserProblemFactChange expected = new DisableUserProblemFactChange(user);
assertChangeIsTheChangeSetId(result, 0);
assertChange(result, 1, expected);
assertThatUserProcessorsWereNotApplied();
}
use of org.kie.kogito.taskassigning.core.model.User in project kogito-apps by kiegroup.
the class TaskAssigningService method onPlanningExecuted.
/**
* Invoked when the PlanningExecutor finalized the execution of a plan.
* Three main scenarios might happen:
* a) There are successful invocations and thus tasks were assigned, the corresponding "pinning changes" must be produced.
* Create and add them to the Solver.
*
* b) No "pinning changes" to execute there and no available events, retry with the planning items that failed.
*
* c) No "pinning changes" but there are available events, execute them.
*
* @param result a PlanningExecutionResult with results of the planning execution.
*/
synchronized void onPlanningExecuted(PlanningExecutionResult result) {
if (isNotOperative()) {
LOGGER.warn(SERVICE_INOPERATIVE_MESSAGE, context.getStatus());
return;
}
try {
LOGGER.debug("Planning was executed");
applyingPlanningExecutionResult.set(false);
TaskAssigningSolution solution = currentSolution.get();
Map<String, User> usersById = solution.getUserList().stream().collect(Collectors.toMap(User::getId, Function.identity()));
List<ProblemFactChange<TaskAssigningSolution>> pinningChanges = new ArrayList<>();
Task task;
User user;
boolean published;
for (PlanningExecutionResultItem resultItem : result.getItems()) {
task = resultItem.getItem().getTask();
published = !resultItem.hasError();
if (published) {
user = usersById.get(resultItem.getItem().getTargetUser());
pinningChanges.add(new AssignTaskProblemFactChange(new TaskAssignment(task), user));
}
context.setTaskPublished(task.getId(), published);
}
if (!pinningChanges.isEmpty()) {
LOGGER.debug("Pinning changes must be executed for the successful invocations: {}", pinningChanges.size());
pinningChanges.add(0, scoreDirector -> context.setCurrentChangeSetId(context.nextChangeSetId()));
applyingPlanningExecutionResult.set(true);
cancelScheduledImproveSolutionOnBackgroundTimer();
solverExecutor.addProblemFactChanges(pinningChanges);
} else if (!hasQueuedEvents()) {
List<PlanningItem> failingItems = result.getItems().stream().filter(PlanningExecutionResultItem::hasError).map(PlanningExecutionResultItem::getItem).collect(Collectors.toList());
LOGGER.debug("No new events to process, but some items failed: {}, we must retry", failingItems.size());
cancelScheduledImproveSolutionOnBackgroundTimer();
planningExecutor.start(failingItems, this::onPlanningExecuted);
} else {
LOGGER.debug("Some items failed but there are events to process, try to adjust the solution accordingly.");
resumeEvents();
}
} catch (Exception e) {
failFast(e);
}
}
use of org.kie.kogito.taskassigning.core.model.User in project kogito-apps by kiegroup.
the class SolutionChangesBuilder method addTaskChanges.
private void addTaskChanges(TaskAssignment taskAssignment, TaskData taskData) {
String taskState = taskData.getState();
if (READY.value().equals(taskState)) {
context.setTaskPublished(taskData.getId(), false);
releasedTasksChanges.add(new ReleaseTaskProblemFactChange(taskAssignment));
} else if (RESERVED.value().equals(taskState)) {
context.setTaskPublished(taskData.getId(), true);
if (!taskData.getActualOwner().equals(taskAssignment.getUser().getId()) || !taskAssignment.isPinned()) {
final User user = getUser(usersById.get(taskData.getActualOwner()), taskData.getActualOwner());
AssignTaskProblemFactChange change = new AssignTaskProblemFactChange(taskAssignment, user, true);
addChangeToUser(assignToUserChangesByUserId, change, user, -1, true);
}
} else if (TaskState.isTerminal(taskState)) {
removedTasksSet.add(taskAssignment);
}
if (!removedTasksSet.contains(taskAssignment)) {
Task updatedTask = fromTaskData(taskData);
if (!equalsByTaskInfoProperties(taskAssignment.getTask(), updatedTask)) {
processorRegistry.applyAttributesProcessor(updatedTask, updatedTask.getAttributes());
} else {
updatedTask.setAttributes(taskAssignment.getTask().getAttributes());
}
taskPropertyChanges.add(new TaskInfoChangeProblemFactChange(taskAssignment, updatedTask));
}
}
use of org.kie.kogito.taskassigning.core.model.User in project kogito-apps by kiegroup.
the class SolutionChangesBuilder method addFullSyncUserChanges.
private void addFullSyncUserChanges(List<org.kie.kogito.taskassigning.user.service.User> externalUserList) {
final Set<String> updatedUserIds = new HashSet<>();
externalUserList.stream().filter(externalUser -> !IS_PLANNING_USER.test(externalUser.getId())).map(externalUser -> fromExternalUser(externalUser, processorRegistry)).forEach(synchedUser -> {
final User previousUser = usersById.get(synchedUser.getId());
updatedUserIds.add(synchedUser.getId());
if (previousUser == null) {
// add brand new users
newUserChanges.add(new AddUserProblemFactChange(synchedUser));
} else if (!equalsByProperties(previousUser, synchedUser)) {
// update the users that has changes.
updateUserChanges.add(new UserPropertyChangeProblemFactChange(previousUser, true, synchedUser.getAttributes(), synchedUser.getGroups()));
}
});
// current users not present in the synchronization data set are marked for disabling.
usersById.values().stream().filter(previousUser -> !IS_PLANNING_USER.test(previousUser.getId())).filter(previousUser -> !updatedUserIds.contains(previousUser.getId())).filter(User::isEnabled).forEach(previousUser -> updateUserChanges.add(new DisableUserProblemFactChange(previousUser)));
}
use of org.kie.kogito.taskassigning.core.model.User in project kogito-apps by kiegroup.
the class SolutionChangesBuilder method build.
public List<ProblemFactChange<TaskAssigningSolution>> build() {
usersById = solution.getUserList().stream().collect(Collectors.toMap(User::getId, Function.identity()));
Map<String, TaskAssignment> taskAssignmentById = filterNonDummyAssignments(solution.getTaskAssignmentList()).stream().collect(Collectors.toMap(TaskAssignment::getId, Function.identity()));
TaskAssignment taskAssignment;
for (TaskData taskData : taskDataList) {
taskAssignment = taskAssignmentById.remove(taskData.getId());
if (taskAssignment == null) {
addNewTaskChanges(taskData);
} else {
addTaskChanges(taskAssignment, taskData);
}
}
for (TaskAssignment removedTask : removedTasksSet) {
removedTaskChanges.add(new RemoveTaskProblemFactChange(removedTask));
}
if (userDataEvent != null) {
addFullSyncUserChanges(userDataEvent.getData());
} else {
addRemovableUserChanges();
}
totalChanges.addAll(newUserChanges);
totalChanges.addAll(removedTaskChanges);
totalChanges.addAll(releasedTasksChanges);
for (List<IndexedElement<AssignTaskProblemFactChange>> assignTaskToUserChanges : assignToUserChangesByUserId.values()) {
List<AssignTaskProblemFactChange> assignTaskChanges = assignTaskToUserChanges.stream().map(IndexedElement::getElement).collect(Collectors.toList());
totalChanges.addAll(assignTaskChanges);
}
totalChanges.addAll(taskPropertyChanges);
totalChanges.addAll(updateUserChanges);
totalChanges.addAll(newTasksChanges);
totalChanges.addAll(removableUserChanges);
traceChanges();
if (!totalChanges.isEmpty()) {
totalChanges.add(0, scoreDirector -> context.setCurrentChangeSetId(context.nextChangeSetId()));
}
return totalChanges;
}
Aggregations