TSK-577 - Tasks should only be deleted if all tasks with the same parent business process id can be cleaned up

This commit is contained in:
Jose Ignacio Recuerda Cambil 2018-08-14 18:55:07 +02:00 committed by Mustapha Zorgati
parent 542e66284b
commit 4c192d79a4
5 changed files with 97 additions and 15 deletions

View File

@ -51,6 +51,7 @@ public class TaskanaEngineConfiguration {
private static final String TASKANA_JOB_TASK_CLEANUP_RUN_EVERY = "taskana.jobs.cleanup.runEvery";
private static final String TASKANA_JOB_TASK_CLEANUP_FIRST_RUN = "taskana.jobs.cleanup.firstRunAt";
private static final String TASKANA_JOB_TASK_CLEANUP_MINIMUM_AGE = "taskana.jobs.cleanup.minimumAge";
private static final String TASKANA_JOB_TASK_CLEANUP_ALL_COMPLETED_SAME_PARENTE_BUSINESS = "taskana.jobs.cleanup.allCompletedSameParentBusiness";
private static final String TASKANA_DOMAINS_PROPERTY = "taskana.domains";
private static final String TASKANA_CLASSIFICATION_TYPES_PROPERTY = "taskana.classification.types";
@ -88,6 +89,7 @@ public class TaskanaEngineConfiguration {
private Instant taskCleanupJobFirstRun = Instant.parse("2018-01-01T00:00:00Z");
private Duration taskCleanupJobRunEvery = Duration.parse("P1D");
private Duration taskCleanupJobMinimumAge = Duration.parse("P14D");
private boolean taskCleanupJobAllCompletedSameParentBusiness = true;
// List of configured domain names
protected List<String> domains = new ArrayList<String>();
@ -202,12 +204,24 @@ public class TaskanaEngineConfiguration {
}
}
String taskCleanupJobAllCompletedSameParentBusinessProperty = props.getProperty(TASKANA_JOB_TASK_CLEANUP_ALL_COMPLETED_SAME_PARENTE_BUSINESS);
if (taskCleanupJobAllCompletedSameParentBusinessProperty != null && !taskCleanupJobAllCompletedSameParentBusinessProperty.isEmpty()) {
try {
taskCleanupJobAllCompletedSameParentBusiness = Boolean.parseBoolean(taskCleanupJobAllCompletedSameParentBusinessProperty);
} catch (Exception e) {
LOGGER.warn("Could not parse taskCleanupJobAllCompletedSameParentBusinessProperty ({}). Using default. Exception: {} ",
taskCleanupJobAllCompletedSameParentBusinessProperty, e.getMessage());
}
}
LOGGER.debug("Configured number of task updates per transaction: {}", jobBatchSize);
LOGGER.debug("Number of retries of failed task updates: {}", maxNumberOfJobRetries);
LOGGER.debug("TaskCleanupJob configuration: first run at {}", taskCleanupJobFirstRun);
LOGGER.debug("TaskCleanupJob configuration: runs every {}", taskCleanupJobRunEvery);
LOGGER.debug("TaskCleanupJob configuration: minimum age of tasks to be cleanup up is {}",
taskCleanupJobMinimumAge);
taskCleanupJobMinimumAge);
LOGGER.debug("TaskCleanupJob configuration: all completed task with the same parent business property id {}",
taskCleanupJobAllCompletedSameParentBusiness);
}
private void initDomains(Properties props) {
@ -467,6 +481,14 @@ public class TaskanaEngineConfiguration {
return taskCleanupJobMinimumAge;
}
public void setTaskCleanupJobAllCompletedSameParentBusiness(boolean taskCleanupJobAllCompletedSameParentBusiness) {
this.taskCleanupJobAllCompletedSameParentBusiness = taskCleanupJobAllCompletedSameParentBusiness;
}
public boolean isTaskCleanupJobAllCompletedSameParentBusiness() {
return taskCleanupJobAllCompletedSameParentBusiness;
}
public String getSchemaName() {
return schemaName;
}

View File

@ -2,16 +2,16 @@ package pro.taskana.jobs;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.BulkOperationResults;
import pro.taskana.TaskSummary;
import pro.taskana.TaskanaEngine;
import pro.taskana.TimeInterval;
import pro.taskana.*;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.TaskanaException;
import pro.taskana.transaction.TaskanaTransactionProvider;
@ -23,11 +23,14 @@ public class TaskCleanupJob extends AbstractTaskanaJob {
private static final Logger LOGGER = LoggerFactory.getLogger(TaskCleanupJob.class);
private static BaseQuery.SortDirection asc = BaseQuery.SortDirection.ASCENDING;
// Parameter
private Instant firstRun;
private Duration runEvery;
private Duration minimumAge;
private int batchSize;
private boolean allCompletedSameParentBusiness;
public TaskCleanupJob(TaskanaEngine taskanaEngine, TaskanaTransactionProvider<Object> txProvider,
ScheduledJob scheduledJob) {
@ -36,6 +39,7 @@ public class TaskCleanupJob extends AbstractTaskanaJob {
runEvery = taskanaEngine.getConfiguration().getTaskCleanupJobRunEvery();
minimumAge = taskanaEngine.getConfiguration().getTaskCleanupJobMinimumAge();
batchSize = taskanaEngine.getConfiguration().getMaxNumberOfTaskUpdatesPerTransaction();
allCompletedSameParentBusiness = taskanaEngine.getConfiguration().isTaskCleanupJobAllCompletedSameParentBusiness();
}
@Override
@ -61,10 +65,40 @@ public class TaskCleanupJob extends AbstractTaskanaJob {
}
private List<TaskSummary> getTasksCompletedBefore(Instant untilDate) {
return taskanaEngineImpl.getTaskService()
.createTaskQuery()
.completedWithin(new TimeInterval(null, untilDate))
.list();
List<TaskSummary> taskList = taskanaEngineImpl.getTaskService()
.createTaskQuery()
.completedWithin(new TimeInterval(null, untilDate))
.orderByBusinessProcessId(asc)
.list();
if (allCompletedSameParentBusiness) {
Map<String, Long> numberParentTasksShouldHave = new HashMap<>();
Map<String, Long> countParentTask = new HashMap<>();
for (TaskSummary task : taskList) {
numberParentTasksShouldHave.put(task.getParentBusinessProcessId(), taskanaEngineImpl.getTaskService().createTaskQuery().parentBusinessProcessIdIn(task.getParentBusinessProcessId()).count());
countParentTask.merge(task.getParentBusinessProcessId(), 1L, Long::sum);
}
List<String> idsList = new ArrayList<>();
numberParentTasksShouldHave.forEach((k, v) -> {
if (v.compareTo(countParentTask.get(k)) == 0) {
idsList.add(k);
}
});
if (idsList.isEmpty()) {
return new ArrayList<>();
}
String[] ids = new String[idsList.size()];
ids = idsList.toArray(ids);
taskList = taskanaEngineImpl.getTaskService()
.createTaskQuery()
.parentBusinessProcessIdIn(ids)
.list();
}
return taskList;
}
private int deleteTasksTransactionally(List<TaskSummary> tasksToBeDeleted) {

View File

@ -10,6 +10,7 @@ import org.junit.runner.RunWith;
import acceptance.AbstractAccTest;
import pro.taskana.Task;
import pro.taskana.TaskService;
import pro.taskana.TaskSummary;
import pro.taskana.exceptions.ClassificationNotFoundException;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.InvalidOwnerException;
@ -22,6 +23,9 @@ import pro.taskana.jobs.TaskCleanupJob;
import pro.taskana.security.JAASRunner;
import pro.taskana.security.WithAccessId;
import java.util.ArrayList;
import java.util.List;
/**
* Acceptance test for all "jobs tasks runner" scenarios.
*/
@ -38,23 +42,45 @@ public class TaskCleanupJobAccTest extends AbstractAccTest {
@WithAccessId(userName = "admin")
@Test
public void shouldCleanCompletedTasksUntilDate() throws Exception {
long totalTasksCount = taskService.createTaskQuery().count();
assertEquals(72, totalTasksCount);
taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(false);
TaskCleanupJob job = new TaskCleanupJob(taskanaEngine, null, null);
job.run();
totalTasksCount = taskService.createTaskQuery().count();
assertEquals(66, totalTasksCount);
}
@WithAccessId(userName = "admin")
@Test
public void shouldNotCleanCompleteTasksAfterDefinedDay()
throws Exception {
public void shouldCleanCompletedTasksUntilDateWithSameParentBussiness() throws Exception {
long totalTasksCount = taskService.createTaskQuery().count();
assertEquals(67, totalTasksCount);
taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(true);
List<TaskSummary> tasks = taskService.createTaskQuery().parentBusinessProcessIdIn("DOC_0000000000000000006").list();
List<String> ids = new ArrayList<>();
tasks.forEach(item -> {
if (item.getCompleted() == null) {
ids.add(item.getTaskId());
}
});
taskService.deleteTasks(ids);
TaskCleanupJob job = new TaskCleanupJob(taskanaEngine, null, null);
job.run();
totalTasksCount = taskService.createTaskQuery().count();
assertEquals(66, totalTasksCount);
}
@WithAccessId(userName = "admin")
@Test
public void shouldNotCleanCompleteTasksAfterDefinedDay() throws Exception {
Task createdTask = createAndCompleteTask();
TaskCleanupJob job = new TaskCleanupJob(taskanaEngine, null, null);
@ -62,7 +88,6 @@ public class TaskCleanupJobAccTest extends AbstractAccTest {
Task completedCreatedTask = taskService.getTask(createdTask.getId());
assertNotNull(completedCreatedTask);
}
private Task createAndCompleteTask() throws NotAuthorizedException, WorkbasketNotFoundException,

View File

@ -5,7 +5,7 @@ INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000002', '2018-01-29
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000003', '2018-01-29 15:55:03', null , null , '2018-01-29 15:55:03', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000003' , 'DOC_0000000000000000003' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , null , 'efg' , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000004', '2018-01-29 15:55:04', null , null , '2018-01-29 15:55:04', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000004' , 'DOC_0000000000000000004' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , null , null , 'ade' , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000005', '2018-01-29 15:55:05', null , null , '2018-01-29 15:55:05', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000005' , 'DOC_0000000000000000005' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000006', '2018-01-29 15:55:06', null , null , '2018-01-29 15:55:06', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000006' , 'DOC_0000000000000000006' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000006', '2018-01-29 15:55:06', null , '2018-01-30 16:55:06', '2018-01-29 15:55:06', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000006' , 'DOC_0000000000000000006' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000007', '2018-01-29 15:55:07', null , null , '2018-01-29 15:55:07', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000007' , 'DOC_0000000000000000007' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , null , null , null , 'ffg' , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000008', '2018-01-29 15:55:08', null , null , '2018-01-29 15:55:08', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000008' , 'DOC_0000000000000000008' , null , '00' , 'PASystem' , '00' , 'VNR' , '22334455' , false , false , null , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000009', '2018-01-29 15:55:09', null , null , '2018-01-29 15:55:09', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000009' , 'DOC_0000000000000000009' , null , '00' , 'PASystem' , '00' , 'VNR' , '22334455' , false , false , null , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null );

View File

@ -11,3 +11,4 @@ taskana.jobs.cleanup.schedule=0 0 3 * * *
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.jobs.cleanup.allCompletedSameParentBusiness=true