diff --git a/history/taskana-loghistory-provider/src/test/resources/taskana.properties b/history/taskana-loghistory-provider/src/test/resources/taskana.properties index 8f740b321..a9a10374c 100644 --- a/history/taskana-loghistory-provider/src/test/resources/taskana.properties +++ b/history/taskana-loghistory-provider/src/test/resources/taskana.properties @@ -14,6 +14,10 @@ taskana.jobs.batchSize=50 taskana.jobs.cleanup.runEvery=P1D taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z taskana.jobs.cleanup.minimumAge=P14D +taskana.jobs.history.batchSize=50 +taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z +taskana.jobs.history.cleanup.minimumAge=P14D +taskana.jobs.history.cleanup.runEvery=P1D taskana.german.holidays.enabled=true taskana.german.holidays.corpus-christi.enabled=true diff --git a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/HistoryCleanupJob.java b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java similarity index 65% rename from history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/HistoryCleanupJob.java rename to history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java index 98ce2d0ec..6db5fe8e0 100644 --- a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/HistoryCleanupJob.java +++ b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java @@ -1,4 +1,8 @@ -package pro.taskana.simplehistory.impl; +package pro.taskana.simplehistory.impl.jobs; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toList; import java.io.File; import java.io.FileInputStream; @@ -8,12 +12,10 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.function.Predicate; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,6 +30,10 @@ import pro.taskana.common.api.exceptions.SystemException; import pro.taskana.common.api.exceptions.TaskanaException; import pro.taskana.common.internal.jobs.AbstractTaskanaJob; import pro.taskana.common.internal.transaction.TaskanaTransactionProvider; +import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl; +import pro.taskana.simplehistory.impl.TaskanaHistoryEngineImpl; +import pro.taskana.spi.history.api.events.task.TaskHistoryEvent; +import pro.taskana.spi.history.api.events.task.TaskHistoryEventType; public class HistoryCleanupJob extends AbstractTaskanaJob { @@ -36,21 +42,25 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { private static final String TASKANA_PROPERTIES = "/taskana.properties"; private static final String TASKANA_JOB_HISTORY_BATCH_SIZE = "taskana.jobs.history.batchSize"; + private static final String TASKANA_JOB_HISTORY_CLEANUP_RUN_EVERY = "taskana.jobs.history.cleanup.runEvery"; + private static final String TASKANA_JOB_HISTORY_CLEANUP_FIRST_RUN = "taskana.jobs.history.cleanup.firstRunAt"; + private static final String TASKANA_JOB_HISTORY_CLEANUP_MINIMUM_AGE = "taskana.jobs.history.cleanup.minimumAge"; + private final boolean allCompletedSameParentBusiness; + TaskanaHistoryEngineImpl taskanaHistoryEngine = TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngineImpl.getConfiguration()); - private Instant firstRun; - private Duration runEvery; - private Duration minimumAge; - private int batchSize; - private boolean allCompletedSameParentBusiness; + private Instant firstRun = Instant.parse("2018-01-01T00:00:00Z"); + private Duration runEvery = Duration.parse("P1D"); + private Duration minimumAge = Duration.parse("P14D"); + private int batchSize = 100; public HistoryCleanupJob( TaskanaEngine taskanaEngine, @@ -75,28 +85,52 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { SimpleHistoryServiceImpl simpleHistoryService = (SimpleHistoryServiceImpl) taskanaHistoryEngine.getTaskanaHistoryService(); - List historyEventsToClean = + List historyEventCandidatesToClean = simpleHistoryService - .createHistoryQuery() + .createTaskHistoryQuery() .createdWithin(new TimeInterval(null, createdBefore)) - .eventTypeIn("TASK_COMPLETED") + .eventTypeIn( + TaskHistoryEventType.COMPLETED.getName(), + TaskHistoryEventType.CANCELLED.getName(), + TaskHistoryEventType.TERMINATED.getName()) .list(); + List taskIdsToDeleteHistoryEventsFor; + if (allCompletedSameParentBusiness) { - historyEventsToClean = - filterSameParentBusinessHistoryEventsQualifiedToClean( - simpleHistoryService, historyEventsToClean); + + String[] parentBusinessProcessIds = + historyEventCandidatesToClean.stream() + .map(TaskHistoryEvent::getParentBusinessProcessId) + .distinct() + .toArray(String[]::new); + + historyEventCandidatesToClean.addAll( + simpleHistoryService + .createTaskHistoryQuery() + .parentBusinessProcessIdIn(parentBusinessProcessIds) + .eventTypeIn(TaskHistoryEventType.CREATED.getName()) + .list()); + + taskIdsToDeleteHistoryEventsFor = + filterSameParentBusinessHistoryEventsQualifiedToClean(historyEventCandidatesToClean); + } else { + taskIdsToDeleteHistoryEventsFor = + historyEventCandidatesToClean.stream() + .map(TaskHistoryEvent::getTaskId) + .collect(toList()); } int totalNumberOfHistoryEventsDeleted = 0; - while (!historyEventsToClean.isEmpty()) { + while (!taskIdsToDeleteHistoryEventsFor.isEmpty()) { int upperLimit = batchSize; - if (upperLimit > historyEventsToClean.size()) { - upperLimit = historyEventsToClean.size(); + if (upperLimit > taskIdsToDeleteHistoryEventsFor.size()) { + upperLimit = taskIdsToDeleteHistoryEventsFor.size(); } totalNumberOfHistoryEventsDeleted += - deleteHistoryEventsTransactionally(historyEventsToClean.subList(0, upperLimit)); - historyEventsToClean.subList(0, upperLimit).clear(); + deleteHistoryEventsTransactionally( + taskIdsToDeleteHistoryEventsFor.subList(0, upperLimit)); + taskIdsToDeleteHistoryEventsFor.subList(0, upperLimit).clear(); } LOGGER.info( "Job ended successfully. {} history events deleted.", totalNumberOfHistoryEventsDeleted); @@ -118,46 +152,50 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { job.scheduleNextCleanupJob(); } - private List filterSameParentBusinessHistoryEventsQualifiedToClean( - SimpleHistoryServiceImpl simpleHistoryService, List historyEventsToClean) { + private List filterSameParentBusinessHistoryEventsQualifiedToClean( + List historyEventCandidatesToClean) { - Map eventsToCleanForParentBusinessCount = new HashMap<>(); + Map>> historyEventsGroupedByParentBusinessProcessIdAndType = + historyEventCandidatesToClean.stream() + .collect( + groupingBy( + TaskHistoryEvent::getParentBusinessProcessId, + groupingBy( + TaskHistoryEvent::getEventType, + mapping(TaskHistoryEvent::getTaskId, toList())))); - historyEventsToClean.forEach( - event -> - eventsToCleanForParentBusinessCount.merge( - event.getParentBusinessProcessId(), 1L, Long::sum)); + List taskIdsToDeleteHistoryEventsFor = new ArrayList<>(); - Predicate noCompletedEventsUnderMinimumAgeExistInSameParentBusiness = - event -> - simpleHistoryService - .createHistoryQuery() - .parentBusinessProcessIdIn(event.getParentBusinessProcessId()) - .eventTypeIn("TASK_COMPLETED") - .count() - == eventsToCleanForParentBusinessCount.get(event.getParentBusinessProcessId()); + historyEventsGroupedByParentBusinessProcessIdAndType + .entrySet() + .forEach( + idsOfTasksInSameParentBusinessProcessGroupedByType -> { + if (idsOfTasksInSameParentBusinessProcessGroupedByType + .getValue() + .get(TaskHistoryEventType.CREATED.getName()) + .size() + == idsOfTasksInSameParentBusinessProcessGroupedByType.getValue().entrySet() + .stream() + .filter( + entry -> !entry.getKey().equals(TaskHistoryEventType.CREATED.getName())) + .mapToInt(stringListEntry -> stringListEntry.getValue().size()) + .sum()) { - Predicate allTasksCleanedSameParentBusiness = - e -> - taskanaEngineImpl - .getTaskService() - .createTaskQuery() - .parentBusinessProcessIdIn(e.getParentBusinessProcessId()) - .count() - == 0; + taskIdsToDeleteHistoryEventsFor.addAll( + idsOfTasksInSameParentBusinessProcessGroupedByType + .getValue() + .get(TaskHistoryEventType.CREATED.getName())); + } + }); - return historyEventsToClean.stream() - .filter( - noCompletedEventsUnderMinimumAgeExistInSameParentBusiness.and( - allTasksCleanedSameParentBusiness)) - .collect(Collectors.toList()); + return taskIdsToDeleteHistoryEventsFor; } - private int deleteHistoryEventsTransactionally(List historyEventsToBeDeleted) { + private int deleteHistoryEventsTransactionally(List taskIdsToDeleteHistoryEventsFor) { if (LOGGER.isDebugEnabled()) { LOGGER.debug( - "entry to deleteHistoryEventsTransactionally(historyEventsToBeDeleted = {})", - historyEventsToBeDeleted); + "entry to deleteHistoryEventsTransactionally(taskIdsToDeleteHistoryEventsFor = {})", + taskIdsToDeleteHistoryEventsFor); } int deletedEventsCount = 0; @@ -167,7 +205,7 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { txProvider.executeInTransaction( () -> { try { - return deleteEvents(historyEventsToBeDeleted); + return deleteEvents(taskIdsToDeleteHistoryEventsFor); } catch (Exception e) { LOGGER.warn("Could not delete history events.", e); return 0; @@ -177,7 +215,7 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { return count; } else { try { - deletedEventsCount = deleteEvents(historyEventsToBeDeleted); + deletedEventsCount = deleteEvents(taskIdsToDeleteHistoryEventsFor); } catch (Exception e) { LOGGER.warn("Could not delete history events.", e); } @@ -187,34 +225,30 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { return deletedEventsCount; } - private int deleteEvents(List historyEventsToBeDeleted) + private int deleteEvents(List taskIdsToDeleteHistoryEventsFor) throws InvalidArgumentException, NotAuthorizedException { if (LOGGER.isDebugEnabled()) { LOGGER.debug( - "entry to deleteEvents(historyEventsToBeDeleted = {})", historyEventsToBeDeleted); + "entry to deleteEvents(taskIdsToDeleteHistoryEventsFor = {})", + taskIdsToDeleteHistoryEventsFor); } - List taskIdsOfEventsToBeDeleted = - historyEventsToBeDeleted.stream() - .map(HistoryEventImpl::getTaskId) - .collect(Collectors.toList()); - SimpleHistoryServiceImpl simpleHistoryService = (SimpleHistoryServiceImpl) taskanaHistoryEngine.getTaskanaHistoryService(); - String[] taskIdsArray = new String[taskIdsOfEventsToBeDeleted.size()]; + String[] taskIdsArray = new String[taskIdsToDeleteHistoryEventsFor.size()]; int deletedTasksCount = (int) simpleHistoryService - .createHistoryQuery() - .taskIdIn(taskIdsOfEventsToBeDeleted.toArray(taskIdsArray)) + .createTaskHistoryQuery() + .taskIdIn(taskIdsToDeleteHistoryEventsFor.toArray(taskIdsArray)) .count(); - simpleHistoryService.deleteHistoryEventsByTaskIds(taskIdsOfEventsToBeDeleted); + simpleHistoryService.deleteHistoryEventsByTaskIds(taskIdsToDeleteHistoryEventsFor); LOGGER.debug("{} events deleted.", deletedTasksCount); - LOGGER.debug("exit from deleteEvents(), returning {}", taskIdsOfEventsToBeDeleted.size()); + LOGGER.debug("exit from deleteEvents(), returning {}", taskIdsToDeleteHistoryEventsFor.size()); return deletedTasksCount; } @@ -315,8 +349,10 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { "taskana properties were loaded from file {} from classpath.", propertiesFile); } } else { - props.load(new FileInputStream(propertiesFile)); - LOGGER.debug("taskana properties were loaded from file {}.", propertiesFile); + try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) { + props.load(fileInputStream); + LOGGER.debug("taskana properties were loaded from file {}.", propertiesFile); + } } } catch (IOException e) { LOGGER.error("caught IOException when processing properties file {}.", propertiesFile); diff --git a/history/taskana-simplehistory-provider/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java b/history/taskana-simplehistory-provider/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java index 5791b5846..931680511 100644 --- a/history/taskana-simplehistory-provider/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java +++ b/history/taskana-simplehistory-provider/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java @@ -11,8 +11,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import pro.taskana.simplehistory.impl.HistoryCleanupJob; -import pro.taskana.simplehistory.impl.HistoryEventImpl; +import pro.taskana.simplehistory.impl.jobs.HistoryCleanupJob; +import pro.taskana.spi.history.api.events.task.TaskHistoryEvent; +import pro.taskana.spi.history.api.events.task.TaskHistoryEventType; @ExtendWith(JaasExtension.class) class HistoryCleanupJobAccTest extends AbstractAccTest { @@ -27,128 +28,336 @@ class HistoryCleanupJobAccTest extends AbstractAccTest { void should_CleanHistoryEventsUntilDate_When_SameParentBusinessTrueAndEventsQualified() throws Exception { - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(13); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(13); - HistoryEventImpl eventToBeCleaned = - createHistoryEvent( - "wbKey1", "taskId1", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); eventToBeCleaned.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); eventToBeCleaned.setParentBusinessProcessId("sameParentId"); - HistoryEventImpl eventToBeCleaned2 = - createHistoryEvent( - "wbKey1", "taskId2", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails"); eventToBeCleaned2.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned3.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned3.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned4 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CANCELLED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned4.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned4.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned5 = + createTaskHistoryEvent( + "wbKey1", + "taskId3", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned5.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned5.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned6 = + createTaskHistoryEvent( + "wbKey1", + "taskId3", + TaskHistoryEventType.TERMINATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned6.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned6.setParentBusinessProcessId("sameParentId"); + getHistoryService().create(eventToBeCleaned); getHistoryService().create(eventToBeCleaned2); + getHistoryService().create(eventToBeCleaned3); + getHistoryService().create(eventToBeCleaned4); + getHistoryService().create(eventToBeCleaned5); + getHistoryService().create(eventToBeCleaned6); - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(15); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(19); taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(true); HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); job.run(); - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(13); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(13); } @Test @WithAccessId(user = "admin") - void should_NotCleanHistoryEventsUntilDate_When_SameParentBusinessTrueAndEventsNotQualified() - throws Exception { + void should_NotCleanHistoryEventsUntilDate_When_MinimumAgeNotReached() throws Exception { - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(13); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(13); - HistoryEventImpl eventToBeCleaned = - createHistoryEvent( - "wbKey1", "taskId1", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); - eventToBeCleaned.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); - eventToBeCleaned.setParentBusinessProcessId("sameParentId"); - - HistoryEventImpl eventToBeCleaned2 = - createHistoryEvent( - "wbKey1", "taskId2", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); - eventToBeCleaned2.setCreated(Instant.now().minus(1, ChronoUnit.DAYS)); - eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); - - HistoryEventImpl eventToBeCleaned3 = - createHistoryEvent( + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( "wbKey1", - "TKI:000000000000000000000000000000000001", - "TASK_COMPLETED", + "taskId1", + TaskHistoryEventType.CREATED.getName(), "wbKey2", "someUserId", "someDetails"); - eventToBeCleaned3.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); - eventToBeCleaned3.setParentBusinessProcessId("PBPI21"); + eventToBeCleaned.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned2.setCreated(Instant.now().minus(5, ChronoUnit.DAYS)); + eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); + + getHistoryService().create(eventToBeCleaned); + getHistoryService().create(eventToBeCleaned2); + + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(15); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(15); + } + + @Test + @WithAccessId(user = "admin") + void should_NotCleanHistoryEvents_When_SameParentBusinessTrueAndActiveTaskInParentBusiness() + throws Exception { + + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(13); + + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned2.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned3.setCreated(Instant.now().minus(1, ChronoUnit.DAYS)); + eventToBeCleaned3.setParentBusinessProcessId("sameParentId"); getHistoryService().create(eventToBeCleaned); getHistoryService().create(eventToBeCleaned2); getHistoryService().create(eventToBeCleaned3); - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(16); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(16); taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(true); HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); job.run(); - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(16); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(16); + } + + @Test + @WithAccessId(user = "admin") + void should_NotCleanHistoryEvents_When_MinimumAgeOfOtherEndtstateEventInParentBusinessNotReached() + throws Exception { + + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(13); + + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned2.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned3.setCreated(Instant.now().minus(3, ChronoUnit.DAYS)); + eventToBeCleaned3.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned4 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CANCELLED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned4.setCreated(Instant.now().minus(5, ChronoUnit.DAYS)); + eventToBeCleaned4.setParentBusinessProcessId("sameParentId"); + + getHistoryService().create(eventToBeCleaned); + getHistoryService().create(eventToBeCleaned2); + getHistoryService().create(eventToBeCleaned3); + getHistoryService().create(eventToBeCleaned4); + + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(17); + + taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(true); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(17); } @Test @WithAccessId(user = "admin") void should_CleanHistoryEventsUntilDate_When_SameParentBusinessFalse() throws Exception { - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(13); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(13); - HistoryEventImpl eventToBeCleaned = - createHistoryEvent( - "wbKey1", "taskId1", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); eventToBeCleaned.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); eventToBeCleaned.setParentBusinessProcessId("sameParentId"); - HistoryEventImpl eventToBeCleaned2 = - createHistoryEvent( - "wbKey1", "taskId2", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); - eventToBeCleaned2.setCreated(Instant.now().minus(1, ChronoUnit.DAYS)); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned2.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned3.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned3.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned4 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CANCELLED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned4.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned4.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned5 = + createTaskHistoryEvent( + "wbKey1", + "taskId3", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned5.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); + eventToBeCleaned5.setParentBusinessProcessId("sameParentId"); + + TaskHistoryEvent eventToBeCleaned6 = + createTaskHistoryEvent( + "wbKey1", + "taskId3", + TaskHistoryEventType.TERMINATED.getName(), + "wbKey2", + "someUserId", + "someDetails"); + eventToBeCleaned6.setCreated(Instant.now().minus(5, ChronoUnit.DAYS)); + eventToBeCleaned6.setParentBusinessProcessId("sameParentId"); + getHistoryService().create(eventToBeCleaned); getHistoryService().create(eventToBeCleaned2); + getHistoryService().create(eventToBeCleaned3); + getHistoryService().create(eventToBeCleaned4); + getHistoryService().create(eventToBeCleaned5); + getHistoryService().create(eventToBeCleaned6); - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(15); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(19); taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(false); HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); job.run(); - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(14); - assertThat(getHistoryService().getHistoryEvent(eventToBeCleaned2.getId())).isNotNull(); - } - - @Test - @WithAccessId(user = "admin") - void should_NotCleanHistoryEvents_When_MinimumAgeNotReached() throws Exception { - - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(13); - - HistoryEventImpl eventToBeCleaned = - createHistoryEvent( - "wbKey1", "taskId1", "TASK_COMPLETED", "wbKey2", "someUserId", "someDetails"); - eventToBeCleaned.setCreated(Instant.now().minus(1, ChronoUnit.DAYS)); - eventToBeCleaned.setParentBusinessProcessId("sameParentId"); - - getHistoryService().create(eventToBeCleaned); - - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(14); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createHistoryQuery().count()).isEqualTo(14); + assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(15); } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/common/api/ScheduledJob.java b/lib/taskana-core/src/main/java/pro/taskana/common/api/ScheduledJob.java index c1ea99d2e..4c15b17af 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/common/api/ScheduledJob.java +++ b/lib/taskana-core/src/main/java/pro/taskana/common/api/ScheduledJob.java @@ -181,7 +181,7 @@ public class ScheduledJob { UPDATETASKSJOB(TaskRefreshJob.class.getName()), TASKCLEANUPJOB(TaskCleanupJob.class.getName()), WORKBASKETCLEANUPJOB(WorkbasketCleanupJob.class.getName()), - HISTORYCLEANUPJOB("pro.taskana.simplehistory.impl.HistoryCleanupJob"); + HISTORYCLEANUPJOB("pro.taskana.simplehistory.impl.jobs.HistoryCleanupJob"); private String clazz; diff --git a/lib/taskana-core/src/main/java/pro/taskana/common/internal/jobs/AbstractTaskanaJob.java b/lib/taskana-core/src/main/java/pro/taskana/common/internal/jobs/AbstractTaskanaJob.java index abf474ec5..c053d43e5 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/common/internal/jobs/AbstractTaskanaJob.java +++ b/lib/taskana-core/src/main/java/pro/taskana/common/internal/jobs/AbstractTaskanaJob.java @@ -5,15 +5,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import pro.taskana.classification.internal.jobs.ClassificationChangedJob; import pro.taskana.common.api.ScheduledJob; import pro.taskana.common.api.TaskanaEngine; -import pro.taskana.common.api.exceptions.TaskanaException; import pro.taskana.common.internal.TaskanaEngineImpl; import pro.taskana.common.internal.transaction.TaskanaTransactionProvider; -import pro.taskana.task.internal.jobs.TaskCleanupJob; -import pro.taskana.task.internal.jobs.TaskRefreshJob; -import pro.taskana.workbasket.internal.jobs.WorkbasketCleanupJob; /** Abstract base for all background jobs of TASKANA. */ public abstract class AbstractTaskanaJob implements TaskanaJob { @@ -33,34 +28,15 @@ public abstract class AbstractTaskanaJob implements TaskanaJob { public static TaskanaJob createFromScheduledJob( TaskanaEngine engine, TaskanaTransactionProvider txProvider, ScheduledJob job) - throws TaskanaException, ClassNotFoundException, IllegalAccessException, - InstantiationException, InvocationTargetException { + throws ClassNotFoundException, IllegalAccessException, InstantiationException, + InvocationTargetException { - switch (job.getType()) { - case CLASSIFICATIONCHANGEDJOB: - return new ClassificationChangedJob(engine, txProvider, job); - case UPDATETASKSJOB: - return new TaskRefreshJob(engine, txProvider, job); - case TASKCLEANUPJOB: - return new TaskCleanupJob(engine, txProvider, job); - case WORKBASKETCLEANUPJOB: - return new WorkbasketCleanupJob(engine, txProvider, job); - case HISTORYCLEANUPJOB: - return (TaskanaJob) - Thread.currentThread() - .getContextClassLoader() - .loadClass(job.getType().getClazz()) - .getConstructors()[0] - .newInstance(engine, txProvider, job); - - default: - throw new TaskanaException( - "No matching job found for " - + job.getType() - + " of ScheduledJob " - + job.getJobId() - + "."); - } + return (TaskanaJob) + Thread.currentThread() + .getContextClassLoader() + .loadClass(job.getType().getClazz()) + .getConstructors()[0] + .newInstance(engine, txProvider, job); } protected List> partition(Collection members, int maxSize) { diff --git a/lib/taskana-spring-example/src/main/resources/taskana.properties b/lib/taskana-spring-example/src/main/resources/taskana.properties index 5af925012..f95ea426c 100644 --- a/lib/taskana-spring-example/src/main/resources/taskana.properties +++ b/lib/taskana-spring-example/src/main/resources/taskana.properties @@ -13,3 +13,7 @@ taskana.jobs.cleanup.runEvery=P1D taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z taskana.jobs.cleanup.minimumAge=PT0S taskana.jobs.cleanup.allCompletedSameParentBusiness=false +taskana.jobs.history.batchSize=50 +taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z +taskana.jobs.history.cleanup.minimumAge=P14D +taskana.jobs.history.cleanup.runEvery=P1D diff --git a/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties b/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties index 74b5352c3..9e6f47685 100644 --- a/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties +++ b/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties @@ -14,6 +14,10 @@ taskana.jobs.batchSize=50 taskana.jobs.cleanup.runEvery=P1D taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z taskana.jobs.cleanup.minimumAge=P14D +taskana.jobs.history.batchSize=50 +taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z +taskana.jobs.history.cleanup.minimumAge=P14D +taskana.jobs.history.cleanup.runEvery=P1D taskana.german.holidays.enabled=true taskana.german.holidays.corpus-christi.enabled=true taskana.historylogger.name=AUDIT diff --git a/rest/taskana-rest-spring-example-wildfly/src/main/resources/taskana.properties b/rest/taskana-rest-spring-example-wildfly/src/main/resources/taskana.properties index 1798e6ac9..e6b084b86 100644 --- a/rest/taskana-rest-spring-example-wildfly/src/main/resources/taskana.properties +++ b/rest/taskana-rest-spring-example-wildfly/src/main/resources/taskana.properties @@ -14,4 +14,8 @@ taskana.jobs.batchSize=50 taskana.jobs.cleanup.runEvery=P1D taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z taskana.jobs.cleanup.minimumAge=P14D +taskana.jobs.history.batchSize=50 +taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z +taskana.jobs.history.cleanup.minimumAge=P14D +taskana.jobs.history.cleanup.runEvery=P1D taskana.german.holidays.enabled=true diff --git a/rest/taskana-rest-spring-example-wildfly/src/test/java/pro/taskana/AbstractAccTest.java b/rest/taskana-rest-spring-example-wildfly/src/test/java/pro/taskana/AbstractAccTest.java index 671505fb1..ed2b7244a 100644 --- a/rest/taskana-rest-spring-example-wildfly/src/test/java/pro/taskana/AbstractAccTest.java +++ b/rest/taskana-rest-spring-example-wildfly/src/test/java/pro/taskana/AbstractAccTest.java @@ -28,7 +28,7 @@ import pro.taskana.workbasket.rest.models.WorkbasketSummaryRepresentationModel; public class AbstractAccTest { - protected static final String DEPENDENCY_VERSION = "4.0.1-SNAPSHOT"; + protected static final String DEPENDENCY_VERSION = "4.0.2-SNAPSHOT"; private static final String AUTHORIZATION_TEAMLEAD_1 = "Basic dGVhbWxlYWQtMTp0ZWFtbGVhZC0x"; /** diff --git a/rest/taskana-rest-spring-example-wildfly/src/test/resources/taskana.properties b/rest/taskana-rest-spring-example-wildfly/src/test/resources/taskana.properties index 60973f58a..3805d91e5 100644 --- a/rest/taskana-rest-spring-example-wildfly/src/test/resources/taskana.properties +++ b/rest/taskana-rest-spring-example-wildfly/src/test/resources/taskana.properties @@ -14,5 +14,9 @@ taskana.jobs.batchSize=50 taskana.jobs.cleanup.runEvery=P1D taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z taskana.jobs.cleanup.minimumAge=P14D +taskana.jobs.history.batchSize=50 +taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z +taskana.jobs.history.cleanup.minimumAge=P14D +taskana.jobs.history.cleanup.runEvery=P1D taskana.german.holidays.enabled=true taskana.historylogger.name=AUDIT