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 deleted file mode 100644 index 4601a5c89..000000000 --- a/history/taskana-simplehistory-provider/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java +++ /dev/null @@ -1,519 +0,0 @@ -package acceptance.jobs; - -import static org.assertj.core.api.Assertions.assertThat; - -import acceptance.AbstractAccTest; -import java.sql.SQLException; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DynamicTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestFactory; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.function.ThrowingConsumer; -import pro.taskana.TaskanaConfiguration; -import pro.taskana.classification.internal.jobs.ClassificationChangedJob; -import pro.taskana.common.api.ScheduledJob; -import pro.taskana.common.internal.jobs.AbstractTaskanaJob; -import pro.taskana.common.internal.util.Pair; -import pro.taskana.common.test.config.DataSourceGenerator; -import pro.taskana.common.test.security.JaasExtension; -import pro.taskana.common.test.security.WithAccessId; -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; -import pro.taskana.task.internal.jobs.TaskRefreshJob; - -@ExtendWith(JaasExtension.class) -class HistoryCleanupJobAccTest extends AbstractAccTest { - - @BeforeEach - void before() throws Exception { - resetDb(DataSourceGenerator.getSchemaName()); - } - - @Test - @WithAccessId(user = "admin") - void should_CleanHistoryEventsUntilDate_When_SameParentBusinessTrueAndEventsQualified() - throws Exception { - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - - 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(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().createTaskHistoryQuery().count()).isEqualTo(20); - - createTaskanaEngineWithNewConfig(true); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - } - - @Test - @WithAccessId(user = "admin") - void should_NotCleanHistoryEventsUntilDate_When_MinimumAgeNotReached() throws Exception { - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - - 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(5, ChronoUnit.DAYS)); - eventToBeCleaned2.setParentBusinessProcessId("sameParentId"); - - getHistoryService().create(eventToBeCleaned); - getHistoryService().create(eventToBeCleaned2); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(16); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(16); - } - - @Test - @WithAccessId(user = "admin") - void should_NotCleanHistoryEvents_When_SameParentBusinessTrueAndActiveTaskInParentBusiness() - throws Exception { - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - - 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().createTaskHistoryQuery().count()).isEqualTo(17); - - createTaskanaEngineWithNewConfig(true); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(17); - } - - @Test - @WithAccessId(user = "admin") - void should_NotCleanHistoryEvents_When_MinimumAgeOfOtherEndtstateEventInParentBusinessNotReached() - throws Exception { - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - - 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(18); - - createTaskanaEngineWithNewConfig(true); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(18); - } - - @Test - @WithAccessId(user = "admin") - void should_CleanHistoryEventsUntilDate_When_SameParentBusinessFalse() throws Exception { - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - - 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(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().createTaskHistoryQuery().count()).isEqualTo(20); - - createTaskanaEngineWithNewConfig(false); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(16); - } - - @Test - @WithAccessId(user = "admin") - void should_NotCleanEvents_When_NoCreatedEventsForParentBusinessProcessIdExist() - throws Exception { - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(14); - - TaskHistoryEvent toBeIgnored1 = - createTaskHistoryEvent( - "wbKey1", - "taskId1", - TaskHistoryEventType.CANCELLED.getName(), - "wbKey2", - "someUserId", - "someDetails"); - toBeIgnored1.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); - toBeIgnored1.setParentBusinessProcessId("toBeIgnored1"); - - TaskHistoryEvent toBeIgnored2 = - createTaskHistoryEvent( - "wbKey1", - "taskId2", - TaskHistoryEventType.COMPLETED.getName(), - "wbKey2", - "someUserId", - "someDetails"); - toBeIgnored2.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); - toBeIgnored2.setParentBusinessProcessId("toBeIgnored2"); - - TaskHistoryEvent toBeIgnored3 = - createTaskHistoryEvent( - "wbKey1", - "taskId3", - TaskHistoryEventType.TERMINATED.getName(), - "wbKey2", - "someUserId", - "someDetails"); - toBeIgnored3.setCreated(Instant.now().minus(20, ChronoUnit.DAYS)); - toBeIgnored3.setParentBusinessProcessId("toBeIgnored3"); - - getHistoryService().create(toBeIgnored1); - getHistoryService().create(toBeIgnored2); - getHistoryService().create(toBeIgnored3); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(17); - - createTaskanaEngineWithNewConfig(true); - - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - job.run(); - - assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(17); - } - - @WithAccessId(user = "admin") - @Test - void should_DeleteOldHistoryCleanupJobs_When_InitializingSchedule() throws Exception { - - for (int i = 0; i < 10; i++) { - ScheduledJob job = new ScheduledJob(); - job.setType(HistoryCleanupJob.class.getName()); - taskanaEngine.getJobService().createJob(job); - job.setType(TaskRefreshJob.class.getName()); - taskanaEngine.getJobService().createJob(job); - job.setType(ClassificationChangedJob.class.getName()); - taskanaEngine.getJobService().createJob(job); - } - - List jobsToRun = getJobMapper().findJobsToRun(Instant.now()); - - assertThat(jobsToRun).hasSize(30); - - List historyCleanupJobs = - jobsToRun.stream() - .filter( - scheduledJob -> scheduledJob.getType().equals(HistoryCleanupJob.class.getName())) - .collect(Collectors.toList()); - - AbstractTaskanaJob.initializeSchedule(taskanaEngine, HistoryCleanupJob.class); - - jobsToRun = getJobMapper().findJobsToRun(Instant.now()); - - assertThat(jobsToRun).doesNotContainAnyElementsOf(historyCleanupJobs); - } - - @WithAccessId(user = "admin") - @TestFactory - Stream - should_CleanTaskHistoryEventsWithParentProcessIdEmptyOrNull_When_TaskCompleted() - throws SQLException { - Iterator iterator = Arrays.asList("", null).iterator(); - String taskId1 = "taskId1"; - String taskId2 = "taskId2"; - List events = - Stream.of( - Pair.of(taskId1, TaskHistoryEventType.CREATED), - Pair.of(taskId1, TaskHistoryEventType.COMPLETED), - Pair.of(taskId2, TaskHistoryEventType.CREATED)) - .map( - pair -> - createTaskHistoryEvent( - "wbKey1", - pair.getLeft(), - pair.getRight().getName(), - "wbKey2", - "someUserId", - "someDetails")) - .collect(Collectors.toList()); - - createTaskanaEngineWithNewConfig(true); - HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); - - ThrowingConsumer test = - parentBusinessId -> { - getHistoryService().deleteHistoryEventsByTaskIds(List.of(taskId1, taskId2)); - events.forEach(x -> x.setCreated(Instant.now().minus(20, ChronoUnit.DAYS))); - events.forEach(x -> x.setParentBusinessProcessId(parentBusinessId)); - events.forEach(x -> getHistoryService().create(x)); - - job.run(); - List eventsAfterCleanup = - getHistoryService().createTaskHistoryQuery().taskIdIn(taskId1, taskId2).list(); - - assertThat(eventsAfterCleanup) - .extracting(TaskHistoryEvent::getTaskId) - .containsExactly(taskId2); - }; - - return DynamicTest.stream(iterator, c -> "for parentBusinessProcessId = '" + c + "'", test); - } - - private void createTaskanaEngineWithNewConfig( - boolean simpleHistoryCleanupJobAllCompletedSameParentBusiness) throws SQLException { - - TaskanaConfiguration configuration = - new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration) - .simpleHistoryCleanupJobAllCompletedSameParentBusiness( - simpleHistoryCleanupJobAllCompletedSameParentBusiness) - .build(); - initTaskanaEngine(configuration); - } -} diff --git a/lib/taskana-core-test/pom.xml b/lib/taskana-core-test/pom.xml index 5144967ab..6cbc1cfce 100644 --- a/lib/taskana-core-test/pom.xml +++ b/lib/taskana-core-test/pom.xml @@ -37,6 +37,12 @@ ${project.version} test + + pro.taskana.history + taskana-simplehistory-provider + ${project.version} + test + org.slf4j slf4j-simple diff --git a/lib/taskana-core-test/src/test/java/acceptance/jobs/AbstractTaskanaJobAccTest.java b/lib/taskana-core-test/src/test/java/acceptance/jobs/AbstractTaskanaJobAccTest.java index d4536b2b6..bf2f2347d 100644 --- a/lib/taskana-core-test/src/test/java/acceptance/jobs/AbstractTaskanaJobAccTest.java +++ b/lib/taskana-core-test/src/test/java/acceptance/jobs/AbstractTaskanaJobAccTest.java @@ -8,12 +8,16 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.api.function.ThrowingConsumer; import pro.taskana.TaskanaConfiguration; import pro.taskana.TaskanaConfiguration.Builder; import pro.taskana.classification.internal.jobs.ClassificationChangedJob; @@ -25,6 +29,8 @@ import pro.taskana.common.internal.JobMapper; import pro.taskana.common.internal.jobs.AbstractTaskanaJob; import pro.taskana.common.internal.jobs.JobRunner; import pro.taskana.common.internal.transaction.TaskanaTransactionProvider; +import pro.taskana.common.internal.util.Pair; +import pro.taskana.simplehistory.impl.jobs.HistoryCleanupJob; import pro.taskana.task.internal.jobs.TaskCleanupJob; import pro.taskana.task.internal.jobs.TaskRefreshJob; import pro.taskana.testapi.TaskanaConfigurationModifier; @@ -49,6 +55,7 @@ class AbstractTaskanaJobAccTest { jobMapper.deleteMultiple(TaskCleanupJob.class.getName()); jobMapper.deleteMultiple(TaskRefreshJob.class.getName()); jobMapper.deleteMultiple(ClassificationChangedJob.class.getName()); + jobMapper.deleteMultiple(HistoryCleanupJob.class.getName()); } @WithAccessId(user = "admin") @@ -75,36 +82,6 @@ class AbstractTaskanaJobAccTest { assertThat(jobsToRun).extracting(ScheduledJob::getDue).containsExactly(firstDue.plus(runEvery)); } - @WithAccessId(user = "admin") - @Test - void should_DeleteOldTaskCleanupJobs_When_InitializingSchedule() { - - for (int i = 0; i < 10; i++) { - ScheduledJob job = new ScheduledJob(); - job.setType(TaskCleanupJob.class.getName()); - taskanaEngine.getJobService().createJob(job); - job.setType(TaskRefreshJob.class.getName()); - taskanaEngine.getJobService().createJob(job); - job.setType(ClassificationChangedJob.class.getName()); - taskanaEngine.getJobService().createJob(job); - } - - List jobsToRun = jobMapper.findJobsToRun(Instant.now()); - - assertThat(jobsToRun).hasSize(30); - - List taskCleanupJobs = - jobsToRun.stream() - .filter(scheduledJob -> scheduledJob.getType().equals(TaskCleanupJob.class.getName())) - .collect(Collectors.toList()); - - AbstractTaskanaJob.initializeSchedule(taskanaEngine, TaskCleanupJob.class); - - jobsToRun = jobMapper.findJobsToRun(Instant.now()); - - assertThat(jobsToRun).doesNotContainAnyElementsOf(taskCleanupJobs); - } - @Nested @TestInstance(Lifecycle.PER_CLASS) class CleanCompletedTasks implements TaskanaConfigurationModifier { @@ -131,6 +108,43 @@ class AbstractTaskanaJobAccTest { } } + @WithAccessId(user = "admin") + @TestFactory + Stream should_DeleteOldCleanupJobs_When_InitializingSchedule() throws Exception { + List>> testCases = + List.of( + Pair.of("Delete Old Task Cleanup Jobs", TaskCleanupJob.class), + Pair.of("Delete Old History Cleanup Jobs", HistoryCleanupJob.class)); + ThrowingConsumer>> test = + t -> { + for (int i = 0; i < 10; i++) { + ScheduledJob job = new ScheduledJob(); + job.setType(t.getRight().getName()); + taskanaEngine.getJobService().createJob(job); + job.setType(TaskRefreshJob.class.getName()); + taskanaEngine.getJobService().createJob(job); + job.setType(ClassificationChangedJob.class.getName()); + taskanaEngine.getJobService().createJob(job); + } + + List jobsToRun = jobMapper.findJobsToRun(Instant.now()); + + List cleanupJobs = + jobsToRun.stream() + .filter(scheduledJob -> scheduledJob.getType().equals(t.getRight().getName())) + .collect(Collectors.toList()); + + AbstractTaskanaJob.initializeSchedule(taskanaEngine, t.getRight()); + + jobsToRun = jobMapper.findJobsToRun(Instant.now()); + + assertThat(jobsToRun).doesNotContainAnyElementsOf(cleanupJobs); + cleanupJobs(); + }; + + return DynamicTest.stream(testCases.iterator(), Pair::getLeft, test); + } + @Test void should_CreateSampleTaskanaJob_When_JobHasMoreThenOneConstructor() { diff --git a/lib/taskana-core-test/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java b/lib/taskana-core-test/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java new file mode 100644 index 000000000..0031e78b8 --- /dev/null +++ b/lib/taskana-core-test/src/test/java/acceptance/jobs/HistoryCleanupJobAccTest.java @@ -0,0 +1,458 @@ +package acceptance.jobs; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.sql.SQLException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.api.function.ThrowingConsumer; +import pro.taskana.TaskanaConfiguration.Builder; +import pro.taskana.common.api.TaskanaEngine; +import pro.taskana.common.internal.util.IdGenerator; +import pro.taskana.common.internal.util.Pair; +import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl; +import pro.taskana.simplehistory.impl.jobs.HistoryCleanupJob; +import pro.taskana.spi.history.api.TaskanaHistory; +import pro.taskana.spi.history.api.events.task.TaskHistoryEvent; +import pro.taskana.spi.history.api.events.task.TaskHistoryEventType; +import pro.taskana.testapi.TaskanaConfigurationModifier; +import pro.taskana.testapi.TaskanaInject; +import pro.taskana.testapi.TaskanaIntegrationTest; +import pro.taskana.testapi.WithServiceProvider; +import pro.taskana.testapi.security.WithAccessId; + +@WithServiceProvider( + serviceProviderInterface = TaskanaHistory.class, + serviceProviders = SimpleHistoryServiceImpl.class) +@TaskanaIntegrationTest +class HistoryCleanupJobAccTest { + + @TaskanaInject TaskanaEngine taskanaEngine; + + SimpleHistoryServiceImpl historyService; + + @WithAccessId(user = "businessadmin") + @BeforeAll + void setup() throws Exception { + historyService = new SimpleHistoryServiceImpl(); + historyService.initialize(taskanaEngine); + } + + @WithAccessId(user = "admin") + @AfterEach + void after() throws Exception { + List taskHistoryEventList = historyService.createTaskHistoryQuery().list(); + List taskIds = taskHistoryEventList.stream().map(TaskHistoryEvent::getTaskId).toList(); + if (!taskIds.isEmpty()) { + historyService.deleteHistoryEventsByTaskIds(taskIds); + } + } + + @Test + @WithAccessId(user = "admin") + void should_NotCleanHistoryEventsUntilDate_When_MinimumAgeNotReached() throws Exception { + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(5, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned2); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(historyService.createTaskHistoryQuery().count()).isEqualTo(2); + } + + private TaskHistoryEvent createTaskHistoryEvent( + String workbasketKey, + String taskId, + String type, + String previousWorkbasketId, + String userid, + String details, + Instant created, + String parentBusinessProcessId) { + TaskHistoryEvent historyEvent = new TaskHistoryEvent(); + historyEvent.setId(IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT)); + historyEvent.setUserId(userid); + historyEvent.setDetails(details); + historyEvent.setWorkbasketKey(workbasketKey); + historyEvent.setTaskId(taskId); + historyEvent.setEventType(type); + historyEvent.setOldValue(previousWorkbasketId); + historyEvent.setCreated(created); + historyEvent.setParentBusinessProcessId(parentBusinessProcessId); + return historyEvent; + } + + @Nested + @TestInstance(Lifecycle.PER_CLASS) + class SimpleHistoryCleanupJobAllCompletedSameParentBusinessIsTrue + implements TaskanaConfigurationModifier { + @TaskanaInject TaskanaEngine taskanaEngine; + SimpleHistoryServiceImpl historyService; + + @Override + public Builder modify(Builder builder) { + return builder.simpleHistoryCleanupJobAllCompletedSameParentBusiness(true); + } + + @WithAccessId(user = "businessadmin") + @BeforeAll + void setup() throws Exception { + historyService = new SimpleHistoryServiceImpl(); + historyService.initialize(taskanaEngine); + } + + @Test + @WithAccessId(user = "admin") + void should_CleanHistoryEventsUntilDate_When_SameParentBusinessTrueAndEventsQualified() + throws Exception { + + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned2); + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned3); + TaskHistoryEvent eventToBeCleaned4 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CANCELLED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned4); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(historyService.createTaskHistoryQuery().count()).isZero(); + } + + @Test + @WithAccessId(user = "admin") + void should_NotCleanHistoryEvents_When_SameParentBusinessTrueAndActiveTaskInParentBusiness() + throws Exception { + + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned2); + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(1, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned3); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(historyService.createTaskHistoryQuery().count()).isEqualTo(3); + } + + @Test + @WithAccessId(user = "admin") + void + should_NotCleanHistoryEvents_When_MinimumAgeOfOtherEndStateEventInParentBusinessNotReached() + throws Exception { + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned2); + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(3, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned3); + TaskHistoryEvent eventToBeCleaned4 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CANCELLED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(5, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned4); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(historyService.createTaskHistoryQuery().count()).isEqualTo(4); + } + + @Test + @WithAccessId(user = "admin") + void should_NotCleanEvents_When_NoCreatedEventsForParentBusinessProcessIdExist() + throws Exception { + TaskHistoryEvent toBeIgnored1 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CANCELLED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "toBeIgnored1"); + historyService.create(toBeIgnored1); + TaskHistoryEvent toBeIgnored2 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "toBeIgnored2"); + historyService.create(toBeIgnored2); + TaskHistoryEvent toBeIgnored3 = + createTaskHistoryEvent( + "wbKey1", + "taskId3", + TaskHistoryEventType.TERMINATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "toBeIgnored3"); + historyService.create(toBeIgnored3); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(historyService.createTaskHistoryQuery().count()).isEqualTo(3); + } + + @WithAccessId(user = "admin") + @TestFactory + Stream + should_CleanTaskHistoryEventsWithParentProcessIdEmptyOrNull_When_TaskCompleted() + throws SQLException { + Iterator iterator = Arrays.asList("", null).iterator(); + String taskId1 = "taskId1"; + String taskId2 = "taskId2"; + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + + ThrowingConsumer test = + parentBusinessId -> { + List events = + Stream.of( + Pair.of(taskId1, TaskHistoryEventType.CREATED), + Pair.of(taskId1, TaskHistoryEventType.COMPLETED), + Pair.of(taskId2, TaskHistoryEventType.CREATED)) + .map( + pair -> + createTaskHistoryEvent( + "wbKey1", + pair.getLeft(), + pair.getRight().getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + parentBusinessId)) + .toList(); + historyService.deleteHistoryEventsByTaskIds(List.of(taskId1, taskId2)); + events.forEach(x -> x.setCreated(Instant.now().minus(20, ChronoUnit.DAYS))); + events.forEach(x -> x.setParentBusinessProcessId(parentBusinessId)); + events.forEach(x -> historyService.create(x)); + + job.run(); + List eventsAfterCleanup = + historyService.createTaskHistoryQuery().taskIdIn(taskId1, taskId2).list(); + + assertThat(eventsAfterCleanup) + .extracting(TaskHistoryEvent::getTaskId) + .containsExactly(taskId2); + }; + + return DynamicTest.stream(iterator, c -> "for parentBusinessProcessId = '" + c + "'", test); + } + } + + @Nested + @TestInstance(Lifecycle.PER_CLASS) + class SimpleHistoryCleanupJobAllCompletedSameParentBusinessIsFalse + implements TaskanaConfigurationModifier { + @TaskanaInject TaskanaEngine taskanaEngine; + SimpleHistoryServiceImpl historyService; + + @Override + public Builder modify(Builder builder) { + return builder.simpleHistoryCleanupJobAllCompletedSameParentBusiness(false); + } + + @WithAccessId(user = "businessadmin") + @BeforeAll + void setup() throws Exception { + historyService = new SimpleHistoryServiceImpl(); + historyService.initialize(taskanaEngine); + } + + @Test + @WithAccessId(user = "admin") + void should_CleanHistoryEventsUntilDate_When_SameParentBusinessFalse() throws Exception { + TaskHistoryEvent eventToBeCleaned = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned); + TaskHistoryEvent eventToBeCleaned2 = + createTaskHistoryEvent( + "wbKey1", + "taskId1", + TaskHistoryEventType.COMPLETED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned2); + TaskHistoryEvent eventToBeCleaned3 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.CREATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(20, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned3); + TaskHistoryEvent eventToBeCleaned4 = + createTaskHistoryEvent( + "wbKey1", + "taskId2", + TaskHistoryEventType.TERMINATED.getName(), + "wbKey2", + "someUserId", + "someDetails", + Instant.now().minus(5, ChronoUnit.DAYS), + "sameParentId"); + historyService.create(eventToBeCleaned4); + + HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); + job.run(); + + assertThat(historyService.createTaskHistoryQuery().count()).isEqualTo(2); + } + } +}