From f113410ef4a5dd89a5368b9a4353319d11491436 Mon Sep 17 00:00:00 2001 From: Joerg Heffner <56156750+gitgoodjhe@users.noreply.github.com> Date: Fri, 16 Oct 2020 08:36:22 +0200 Subject: [PATCH] TSK-1404: Delete old Cleanup jobs when initializing --- .../src/main/resources/sql/clear/clear-db.sql | 3 +- .../impl/jobs/HistoryCleanupJob.java | 3 ++ .../test/java/acceptance/AbstractAccTest.java | 12 +++++++ .../jobs/HistoryCleanupJobAccTest.java | 32 +++++++++++++++++++ .../taskana/common/internal/JobMapper.java | 4 +++ .../common/internal/JobServiceImpl.java | 13 ++++++++ .../task/internal/jobs/TaskCleanupJob.java | 4 +++ .../internal/jobs/WorkbasketCleanupJob.java | 4 +++ .../test/java/acceptance/AbstractAccTest.java | 14 ++++++++ .../jobs/TaskCleanupJobAccTest.java | 31 ++++++++++++++++++ .../jobs/WorkbasketCleanupJobAccTest.java | 31 ++++++++++++++++++ 11 files changed, 149 insertions(+), 2 deletions(-) diff --git a/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql b/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql index 7b892ddbf..600d4940b 100644 --- a/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql +++ b/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql @@ -11,6 +11,5 @@ DELETE FROM WORKBASKET; DELETE FROM DISTRIBUTION_TARGETS; DELETE FROM CLASSIFICATION; DELETE FROM OBJECT_REFERENCE; --- do not clean JOB table --- DELETE FROM SCHEDULED_JOB; +DELETE FROM SCHEDULED_JOB; COMMIT; diff --git a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java index d7bb8dcc3..ea7cff3f6 100644 --- a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java +++ b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/jobs/HistoryCleanupJob.java @@ -28,6 +28,7 @@ import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.common.api.exceptions.SystemException; import pro.taskana.common.api.exceptions.TaskanaException; +import pro.taskana.common.internal.JobServiceImpl; import pro.taskana.common.internal.jobs.AbstractTaskanaJob; import pro.taskana.common.internal.transaction.TaskanaTransactionProvider; import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl; @@ -148,6 +149,8 @@ public class HistoryCleanupJob extends AbstractTaskanaJob { * @param taskanaEngine the TASKANA engine. */ public static void initializeSchedule(TaskanaEngine taskanaEngine) { + JobServiceImpl jobService = (JobServiceImpl) taskanaEngine.getJobService(); + jobService.deleteJobs(Type.HISTORYCLEANUPJOB); HistoryCleanupJob job = new HistoryCleanupJob(taskanaEngine, null, null); job.scheduleNextCleanupJob(); } diff --git a/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java b/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java index a7800d4a2..5b4bc55f5 100644 --- a/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java +++ b/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java @@ -18,6 +18,8 @@ import org.slf4j.LoggerFactory; import pro.taskana.TaskanaEngineConfiguration; import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.TaskanaEngine.ConnectionManagementMode; +import pro.taskana.common.internal.JobMapper; +import pro.taskana.common.internal.TaskanaEngineImpl; import pro.taskana.common.internal.util.IdGenerator; import pro.taskana.sampledata.SampleDataGenerator; import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl; @@ -169,6 +171,16 @@ public abstract class AbstractAccTest { return sqlSessionManager.getMapper(TaskHistoryQueryMapper.class); } + protected JobMapper getJobMapper() throws NoSuchFieldException, IllegalAccessException { + + Field sessionManagerField = TaskanaEngineImpl.class.getDeclaredField("sessionManager"); + sessionManagerField.setAccessible(true); + SqlSessionManager sqlSessionManager = + (SqlSessionManager) sessionManagerField.get(taskanaEngine); + + return sqlSessionManager.getMapper(JobMapper.class); + } + protected ObjectReference createObjectRef( String company, String system, String systemInstance, String type, String value) { ObjectReference objectRef = new ObjectReference(); 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 704945bf4..b6e6d6092 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 @@ -5,10 +5,13 @@ import static org.assertj.core.api.Assertions.assertThat; import acceptance.AbstractAccTest; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; import pro.taskana.common.test.security.JaasExtension; import pro.taskana.common.test.security.WithAccessId; import pro.taskana.simplehistory.impl.jobs.HistoryCleanupJob; @@ -360,4 +363,33 @@ class HistoryCleanupJobAccTest extends AbstractAccTest { assertThat(getHistoryService().createTaskHistoryQuery().count()).isEqualTo(15); } + + @WithAccessId(user = "admin") + @Test + void should_DeleteOldHistoryCleanupJobs_When_InitializingSchedule() throws Exception { + + for (int i = 0; i < 10; i++) { + ScheduledJob job = new ScheduledJob(); + job.setType(ScheduledJob.Type.HISTORYCLEANUPJOB); + taskanaEngine.getJobService().createJob(job); + job.setType(Type.UPDATETASKSJOB); + taskanaEngine.getJobService().createJob(job); + job.setType(Type.CLASSIFICATIONCHANGEDJOB); + taskanaEngine.getJobService().createJob(job); + } + + List jobsToRun = getJobMapper().findJobsToRun(); + + assertThat(jobsToRun).hasSize(30); + + HistoryCleanupJob.initializeSchedule(taskanaEngine); + + jobsToRun = getJobMapper().findJobsToRun(); + + assertThat(jobsToRun).hasSize(20); + + assertThat(jobsToRun) + .extracting(ScheduledJob::getType) + .containsOnly(Type.CLASSIFICATIONCHANGEDJOB, Type.UPDATETASKSJOB); + } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobMapper.java b/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobMapper.java index fea3f977f..6374743aa 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobMapper.java @@ -11,6 +11,7 @@ import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; import pro.taskana.common.internal.persistence.MapTypeHandler; /** This class is the mybatis mapping of the JOB table. */ @@ -70,4 +71,7 @@ public interface JobMapper { @Delete(value = "DELETE FROM SCHEDULED_JOB WHERE JOB_ID = #{jobId}") void delete(ScheduledJob job); + + @Delete(value = "DELETE FROM SCHEDULED_JOB WHERE TYPE = #{jobType}") + void deleteMultiple(Type jobType); } diff --git a/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobServiceImpl.java index 389119cee..4be2d8e8b 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/common/internal/JobServiceImpl.java @@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory; import pro.taskana.common.api.JobService; import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; /** Controls all job activities. */ public class JobServiceImpl implements JobService { @@ -39,6 +40,18 @@ public class JobServiceImpl implements JobService { return job; } + public void deleteJobs(Type jobType) { + LOGGER.debug("entry to deleteJobs(jobType = {})", jobType); + try { + taskanaEngineImpl.openConnection(); + jobMapper.deleteMultiple(jobType); + LOGGER.debug("Deleted jobs of type: {}", jobType); + } finally { + taskanaEngineImpl.returnConnection(); + LOGGER.debug("exit from deleteJobs()"); + } + } + public ScheduledJob lockJob(ScheduledJob job, String owner) { LOGGER.debug("entry to lockJob(jobId = {}, owner = {})", job.getJobId(), owner); try { diff --git a/lib/taskana-core/src/main/java/pro/taskana/task/internal/jobs/TaskCleanupJob.java b/lib/taskana-core/src/main/java/pro/taskana/task/internal/jobs/TaskCleanupJob.java index be50bae78..de61ab4ad 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/task/internal/jobs/TaskCleanupJob.java +++ b/lib/taskana-core/src/main/java/pro/taskana/task/internal/jobs/TaskCleanupJob.java @@ -12,11 +12,13 @@ import org.slf4j.LoggerFactory; import pro.taskana.common.api.BaseQuery.SortDirection; import pro.taskana.common.api.BulkOperationResults; import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.TimeInterval; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.common.api.exceptions.TaskanaException; +import pro.taskana.common.internal.JobServiceImpl; import pro.taskana.common.internal.jobs.AbstractTaskanaJob; import pro.taskana.common.internal.transaction.TaskanaTransactionProvider; import pro.taskana.common.internal.util.LogSanitizer; @@ -80,6 +82,8 @@ public class TaskCleanupJob extends AbstractTaskanaJob { * @param taskanaEngine the TASKANA engine. */ public static void initializeSchedule(TaskanaEngine taskanaEngine) { + JobServiceImpl jobService = (JobServiceImpl) taskanaEngine.getJobService(); + jobService.deleteJobs(Type.TASKCLEANUPJOB); TaskCleanupJob job = new TaskCleanupJob(taskanaEngine, null, null); job.scheduleNextCleanupJob(); } diff --git a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/jobs/WorkbasketCleanupJob.java b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/jobs/WorkbasketCleanupJob.java index e941ec3a2..c225ea1af 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/jobs/WorkbasketCleanupJob.java +++ b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/jobs/WorkbasketCleanupJob.java @@ -9,10 +9,12 @@ import org.slf4j.LoggerFactory; import pro.taskana.common.api.BaseQuery; import pro.taskana.common.api.BulkOperationResults; import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.common.api.exceptions.TaskanaException; +import pro.taskana.common.internal.JobServiceImpl; import pro.taskana.common.internal.jobs.AbstractTaskanaJob; import pro.taskana.common.internal.transaction.TaskanaTransactionProvider; import pro.taskana.workbasket.api.WorkbasketQueryColumnName; @@ -71,6 +73,8 @@ public class WorkbasketCleanupJob extends AbstractTaskanaJob { * @param taskanaEngine the taskana engine */ public static void initializeSchedule(TaskanaEngine taskanaEngine) { + JobServiceImpl jobService = (JobServiceImpl) taskanaEngine.getJobService(); + jobService.deleteJobs(Type.WORKBASKETCLEANUPJOB); WorkbasketCleanupJob job = new WorkbasketCleanupJob(taskanaEngine, null, null); job.scheduleNextCleanupJob(); } diff --git a/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java b/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java index 4cd53ef5c..79eb56959 100644 --- a/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java @@ -1,5 +1,6 @@ package acceptance; +import java.lang.reflect.Field; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; @@ -12,6 +13,7 @@ import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.sql.DataSource; +import org.apache.ibatis.session.SqlSessionManager; import org.junit.jupiter.api.BeforeAll; import pro.taskana.TaskanaEngineConfiguration; @@ -19,6 +21,8 @@ import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.TaskanaEngine.ConnectionManagementMode; import pro.taskana.common.api.TimeInterval; import pro.taskana.common.api.WorkingDaysToDaysConverter; +import pro.taskana.common.internal.JobMapper; +import pro.taskana.common.internal.TaskanaEngineImpl; import pro.taskana.common.internal.TaskanaEngineTestConfiguration; import pro.taskana.sampledata.SampleDataGenerator; import pro.taskana.task.api.models.Attachment; @@ -59,6 +63,16 @@ public abstract class AbstractAccTest { sampleDataGenerator.generateTestData(); } + protected JobMapper getJobMapper() throws NoSuchFieldException, IllegalAccessException { + + Field sessionManagerField = TaskanaEngineImpl.class.getDeclaredField("sessionManager"); + sessionManagerField.setAccessible(true); + SqlSessionManager sqlSessionManager = + (SqlSessionManager) sessionManagerField.get(taskanaEngine); + + return sqlSessionManager.getMapper(JobMapper.class); + } + protected ObjectReference createObjectReference( String company, String system, String systemInstance, String type, String value) { ObjectReference objectReference = new ObjectReference(); diff --git a/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java b/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java index 0335f199e..4a0d86b3f 100644 --- a/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java @@ -9,6 +9,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; import pro.taskana.common.test.security.JaasExtension; import pro.taskana.common.test.security.WithAccessId; import pro.taskana.task.api.TaskService; @@ -85,6 +87,35 @@ class TaskCleanupJobAccTest extends AbstractAccTest { assertThat(completedCreatedTask).isNotNull(); } + @WithAccessId(user = "admin") + @Test + void should_DeleteOldTaskCleanupJobs_When_InitializingSchedule() throws Exception { + + for (int i = 0; i < 10; i++) { + ScheduledJob job = new ScheduledJob(); + job.setType(ScheduledJob.Type.TASKCLEANUPJOB); + taskanaEngine.getJobService().createJob(job); + job.setType(Type.UPDATETASKSJOB); + taskanaEngine.getJobService().createJob(job); + job.setType(Type.CLASSIFICATIONCHANGEDJOB); + taskanaEngine.getJobService().createJob(job); + } + + List jobsToRun = getJobMapper().findJobsToRun(); + + assertThat(jobsToRun).hasSize(30); + + TaskCleanupJob.initializeSchedule(taskanaEngine); + + jobsToRun = getJobMapper().findJobsToRun(); + + assertThat(jobsToRun).hasSize(20); + + assertThat(jobsToRun) + .extracting(ScheduledJob::getType) + .containsOnly(Type.CLASSIFICATIONCHANGEDJOB, Type.UPDATETASKSJOB); + } + private Task createAndCompleteTask() throws Exception { Task newTask = taskService.newTask("user-1-1", "DOMAIN_A"); newTask.setClassificationKey("T2100"); diff --git a/lib/taskana-core/src/test/java/acceptance/jobs/WorkbasketCleanupJobAccTest.java b/lib/taskana-core/src/test/java/acceptance/jobs/WorkbasketCleanupJobAccTest.java index 774e31cfe..caf3f632b 100644 --- a/lib/taskana-core/src/test/java/acceptance/jobs/WorkbasketCleanupJobAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/jobs/WorkbasketCleanupJobAccTest.java @@ -9,6 +9,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import pro.taskana.common.api.BaseQuery; +import pro.taskana.common.api.ScheduledJob; +import pro.taskana.common.api.ScheduledJob.Type; import pro.taskana.common.test.security.JaasExtension; import pro.taskana.common.test.security.WithAccessId; import pro.taskana.task.api.TaskService; @@ -85,6 +87,35 @@ class WorkbasketCleanupJobAccTest extends AbstractAccTest { assertThat(totalWorkbasketCount).isEqualTo(25); } + @WithAccessId(user = "admin") + @Test + void should_DeleteOldWorkbasketCleanupJobs_When_InitializingSchedule() throws Exception { + + for (int i = 0; i < 10; i++) { + ScheduledJob job = new ScheduledJob(); + job.setType(ScheduledJob.Type.WORKBASKETCLEANUPJOB); + taskanaEngine.getJobService().createJob(job); + job.setType(Type.UPDATETASKSJOB); + taskanaEngine.getJobService().createJob(job); + job.setType(Type.CLASSIFICATIONCHANGEDJOB); + taskanaEngine.getJobService().createJob(job); + } + + List jobsToRun = getJobMapper().findJobsToRun(); + + assertThat(jobsToRun).hasSize(30); + + WorkbasketCleanupJob.initializeSchedule(taskanaEngine); + + jobsToRun = getJobMapper().findJobsToRun(); + + assertThat(jobsToRun).hasSize(20); + + assertThat(jobsToRun) + .extracting(ScheduledJob::getType) + .containsOnly(Type.CLASSIFICATIONCHANGEDJOB, Type.UPDATETASKSJOB); + } + private long getNumberTaskNotCompleted(String workbasketId) { return taskService .createTaskQuery()