From 8e4724383d43a3293f1d9c99d98e2311c221e57f Mon Sep 17 00:00:00 2001 From: tinker Date: Tue, 25 Jun 2024 21:29:39 +0800 Subject: [PATCH 01/18] refactor schedule --- .../LatestScheduleTaskLinkRepositoryTest.java | 57 ++ .../ScheduleChangeLogRepositoryTest.java | 72 +++ .../odc/quartz/QuartzJobServiceTest.java | 7 +- .../onlineschemachange/BaseOscTestEnv.java | 6 +- .../TriggerListenerFactory.java | 5 +- .../core/shared/constant/ResourceType.java | 1 + .../V_4_3_0_8__add_schedule_change_log.sql | 18 + .../web/controller/v2/ScheduleController.java | 179 ++++-- .../odc-server/src/main/resources/log4j2.xml | 8 +- .../LatestScheduleTaskLinkEntity.java | 49 ++ .../LatestScheduleTaskLinkRepository.java | 34 ++ .../schedule/ScheduleChangeLogEntity.java | 75 +++ .../schedule/ScheduleChangeLogRepository.java | 35 ++ .../odc/metadb/schedule/ScheduleEntity.java | 4 +- .../metadb/schedule/ScheduleRepository.java | 3 +- .../schedule/ScheduleTaskRepository.java | 8 + .../dlm/model/DataArchiveParameters.java | 15 +- .../dlm/model/DataDeleteParameters.java | 15 +- .../odc/service/dlm/model/OffsetConfig.java | 13 + .../odc/service/flow/FlowInstanceService.java | 53 +- .../PreCheckServiceTaskFailedListener.java | 5 - .../CreateFlowInstanceProcessAspect.java | 41 -- .../service/flow/processor/Preprocessor.java | 2 +- .../ResultSetExportPreprocessor.java | 6 +- .../task/model/DatabaseChangeParameters.java | 4 +- .../model/OnlineSchemaChangeTaskResult.java | 4 +- .../notification/helper/EventBuilder.java | 60 +- .../OnlineSchemaChangeFlowableTask.java | 16 +- .../onlineschemachange/OscService.java | 6 +- .../PartitionPlanScheduleService.java | 10 +- .../odc/service/quartz/OdcJobListener.java | 73 +-- .../service/quartz/OdcTriggerListener.java | 3 +- .../odc/service/quartz/QuartzJobService.java | 51 +- .../quartz/executor/AbstractQuartzJob.java | 6 +- .../schedule/ScheduleChangeLogService.java | 60 ++ .../odc/service/schedule/ScheduleService.java | 572 +++++++----------- .../service/schedule/ScheduleTaskService.java | 268 +++++++- .../ScheduleResponseMapperFactory.java | 232 ++++--- .../flowtask/AlterScheduleParameters.java | 1 + .../schedule/flowtask/AlterScheduleTask.java | 73 +-- .../flowtask/SqlPlanPreprocessor.java | 142 ----- .../service/schedule/job/AbstractDlmJob.java | 166 +---- .../schedule/job/DataArchiveDeleteJob.java | 41 +- .../service/schedule/job/DataArchiveJob.java | 28 +- .../schedule/job/DataArchiveRollbackJob.java | 62 +- .../service/schedule/job/DataDeleteJob.java | 75 +-- .../schedule/job/PartitionPlanJob.java | 4 +- .../odc/service/schedule/job/SqlPlanJob.java | 13 +- .../schedule/model/CreateQuartzJobReq.java | 6 +- .../schedule/model/CreateScheduleReq.java | 76 +++ .../schedule/model/DataArchiveAttributes.java | 36 ++ .../schedule/model/DataDeleteAttributes.java | 38 ++ .../odc/service/schedule/model/JobType.java | 1 + .../{flowtask => model}/OperationType.java | 9 +- .../schedule/model/QuartzJobChangeReq.java | 48 ++ .../schedule/model/QuartzKeyGenerator.java | 18 +- .../schedule/model/QueryScheduleParams.java | 5 +- .../odc/service/schedule/model/Schedule.java | 66 ++ .../schedule/model/ScheduleChangeLog.java | 67 ++ .../model/ScheduleChangeLogMapper.java | 41 ++ .../schedule/model/ScheduleChangeReq.java | 61 ++ .../schedule/model/ScheduleChangeStatus.java | 32 + .../schedule/model/ScheduleDetailResp.java | 189 +----- .../model/ScheduleListAttributes.java | 27 + .../schedule/model/ScheduleListResp.java | 46 ++ .../schedule/model/ScheduleMapper.java | 37 ++ .../schedule/model/ScheduleStatus.java | 6 +- ...cheduleTaskResp.java => ScheduleTask.java} | 22 +- .../model/ScheduleTaskDetailResp.java | 49 ++ .../schedule/model/ScheduleTaskListResp.java | 45 ++ .../model/ScheduleTaskListRespMapper.java | 36 ++ .../schedule/model/ScheduleTaskMapper.java | 4 +- .../model/ScheduleTaskParameters.java | 25 + .../schedule/model/ScheduleTaskType.java | 40 ++ .../service/schedule/model/ScheduleType.java | 35 ++ .../service/schedule/model/TriggerConfig.java | 3 - .../schedule/model/UpdateScheduleReq.java | 53 ++ .../AbstractDlmPreprocessor.java} | 32 +- .../processor/CreateScheduleAspect.java | 127 ++++ .../DataArchivePreprocessor.java | 84 +-- .../DataDeletePreprocessor.java | 56 +- .../schedule/processor/Preprocessor.java | 29 + .../processor/ScheduleTaskPreprocessor.java | 8 +- .../DefaultJobProcessUpdateListener.java | 11 +- .../listener/DefaultJobTerminateListener.java | 2 +- .../listener/JobTerminateNotifyListener.java | 6 +- 86 files changed, 2468 insertions(+), 1689 deletions(-) create mode 100644 server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java create mode 100644 server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java create mode 100644 server/odc-migrate/src/main/resources/migrate/common/V_4_3_0_8__add_schedule_change_log.sql create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepository.java rename server/odc-service/src/main/java/com/oceanbase/odc/service/{schedule/flowtask => flow/processor}/ResultSetExportPreprocessor.java (94%) create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleChangeLogService.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/SqlPlanPreprocessor.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataArchiveAttributes.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataDeleteAttributes.java rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/{flowtask => model}/OperationType.java (85%) create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/Schedule.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLogMapper.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeStatus.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/{ScheduleTaskResp.java => ScheduleTask.java} (76%) create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskDetailResp.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskParameters.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskType.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleType.java create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/UpdateScheduleReq.java rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/{flowtask/AbstractDlmJobPreprocessor.java => processor/AbstractDlmPreprocessor.java} (80%) create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/{flowtask => processor}/DataArchivePreprocessor.java (60%) rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/{flowtask => processor}/DataDeletePreprocessor.java (57%) create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java rename server/odc-service/src/main/java/com/oceanbase/odc/service/{flow => schedule}/processor/ScheduleTaskPreprocessor.java (85%) diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java new file mode 100644 index 0000000000..23e99b8682 --- /dev/null +++ b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.metadb.schedule; + +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.locationtech.jts.util.Assert; +import org.springframework.beans.factory.annotation.Autowired; + +import com.oceanbase.odc.ServiceTestEnv; + +/** + * @Author:tinker + * @Date: 2024/6/20 15:44 + * @Descripition: + */ +public class LatestScheduleTaskLinkRepositoryTest extends ServiceTestEnv { + + @Autowired + private LatestScheduleTaskLinkRepository repository; + + @Test + public void listByScheduleIds() { + LatestScheduleTaskLinkEntity entity = create(); + List entities = repository.findByScheduleIdIn(Collections.singleton(1L)); + Assert.equals(1, entities.size()); + Assert.equals(entity, entities.get(0)); + delete(entity); + } + + private LatestScheduleTaskLinkEntity create() { + LatestScheduleTaskLinkEntity entity = new LatestScheduleTaskLinkEntity(); + entity.setScheduleId(1L); + entity.setScheduleTaskId(99L); + return repository.save(entity); + } + + private void delete(LatestScheduleTaskLinkEntity entity) { + repository.delete(entity); + } +} diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java new file mode 100644 index 0000000000..aaca31074a --- /dev/null +++ b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.metadb.schedule; + +import java.util.List; +import java.util.Optional; + +import org.junit.Test; +import org.locationtech.jts.util.Assert; +import org.springframework.beans.factory.annotation.Autowired; + +import com.oceanbase.odc.ServiceTestEnv; +import com.oceanbase.odc.service.schedule.model.OperationType; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeStatus; + +/** + * @Author:tinker + * @Date: 2024/6/20 15:44 + * @Descripition: + */ +public class ScheduleChangeLogRepositoryTest extends ServiceTestEnv { + + @Autowired + private ScheduleChangeLogRepository repository; + + @Test + public void findByScheduleId() { + ScheduleChangeLogEntity entity = create(); + List byScheduleId = repository.findByScheduleId(entity.getScheduleId()); + Assert.equals(1, byScheduleId.size()); + Assert.equals(entity.getScheduleId(), byScheduleId.get(0).getScheduleId()); + delete(entity); + } + + @Test + public void findByIdAndScheduleId() { + ScheduleChangeLogEntity entity = create(); + Optional optional = + repository.findByIdAndScheduleId(entity.getId(), entity.getScheduleId()); + Assert.isTrue(optional.isPresent()); + Assert.equals(entity.getScheduleId(), optional.get().getScheduleId()); + delete(entity); + } + + private ScheduleChangeLogEntity create() { + ScheduleChangeLogEntity entity = new ScheduleChangeLogEntity(); + entity.setType(OperationType.CREATE); + entity.setScheduleId(1L); + entity.setStatus(ScheduleChangeStatus.PREPARING); + return repository.save(entity); + } + + private void delete(ScheduleChangeLogEntity entity) { + repository.delete(entity); + } + + +} diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java index 5dd07b18b6..b4bb0f3489 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java @@ -28,8 +28,8 @@ import com.oceanbase.odc.ServiceTestEnv; import com.oceanbase.odc.service.quartz.QuartzJobService; import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; -import com.oceanbase.odc.service.schedule.model.JobType; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import com.oceanbase.odc.service.schedule.model.TriggerStrategy; @@ -46,8 +46,7 @@ public class QuartzJobServiceTest extends ServiceTestEnv { @Test public void create() throws SchedulerException, ParseException { CreateQuartzJobReq req = new CreateQuartzJobReq(); - req.setScheduleId(1L); - req.setType(JobType.SQL_PLAN); + req.setJobKey(QuartzKeyGenerator.generateJobKey("1", ScheduleType.SQL_PLAN.name())); TriggerConfig config = new TriggerConfig(); config.setTriggerStrategy(TriggerStrategy.START_AT); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd hh:mm:ss"); @@ -56,7 +55,7 @@ public void create() throws SchedulerException, ParseException { req.setTriggerConfig(config); quartzJobService.createJob(req); Trigger trigger = - quartzJobService.getTrigger(QuartzKeyGenerator.generateTriggerKey(req.getScheduleId(), req.getType())); + quartzJobService.getTrigger(QuartzKeyGenerator.generateTriggerKey("1", ScheduleType.SQL_PLAN.name())); Assert.assertEquals(trigger.getFinalFireTime(), date); } diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java index aeb3d8b989..c4798b8a87 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java @@ -15,7 +15,7 @@ */ package com.oceanbase.odc.service.onlineschemachange; -import static com.oceanbase.odc.service.schedule.model.JobType.ONLINE_SCHEMA_CHANGE_COMPLETE; +import static com.oceanbase.odc.service.schedule.model.ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -65,8 +65,8 @@ import com.oceanbase.odc.service.onlineschemachange.oms.response.OmsProjectProgressResponse; import com.oceanbase.odc.service.onlineschemachange.oms.response.OmsProjectStepVO; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; -import com.oceanbase.odc.service.schedule.model.JobType; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import com.oceanbase.odc.service.schedule.model.TriggerStrategy; import com.oceanbase.odc.service.session.DBSessionManageFacade; @@ -180,7 +180,7 @@ protected ScheduleEntity getScheduleEntity(ConnectionConfig config, OnlineSchema scheduleEntity.setStatus(ScheduleStatus.ENABLED); scheduleEntity.setAllowConcurrent(false); scheduleEntity.setMisfireStrategy(MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING); - scheduleEntity.setJobType(JobType.ONLINE_SCHEMA_CHANGE_COMPLETE); + scheduleEntity.setScheduleType(ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE); scheduleEntity.setJobParametersJson(JsonUtils.toJson(changeParameters)); TriggerConfig triggerConfig = new TriggerConfig(); triggerConfig.setTriggerStrategy(TriggerStrategy.CRON); diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/TriggerListenerFactory.java b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/TriggerListenerFactory.java index e7cf2d723f..c795ba1775 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/TriggerListenerFactory.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/TriggerListenerFactory.java @@ -16,7 +16,7 @@ package com.oceanbase.odc.service.onlineschemachange; -import static com.oceanbase.odc.service.schedule.model.JobType.ONLINE_SCHEMA_CHANGE_COMPLETE; +import static com.oceanbase.odc.service.schedule.model.ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE; import java.util.function.Consumer; @@ -39,7 +39,8 @@ public TriggerListener generateTriggerListener(Long scheduleId, Consumer list( + + // change log + + @RequestMapping("/schedules/{id:[\\d]+}/changes") + public ListResponse listChangeLog(@PathVariable Long id) { + List scheduleChangeLogs = scheduleService.listScheduleChangeLog(id); + return Responses.list(scheduleChangeLogs); + } + + @RequestMapping("/schedules/{id:[\\d]+}/changes/{scheduleChangeLogId:[\\d]+}") + public SuccessResponse getChangeLog(@PathVariable Long id, + @PathVariable Long scheduleChangeLogId) { + return Responses.single(scheduleService.getChangeLog(id, scheduleChangeLogId)); + } + + // schedule task + + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/executions/latest/terminate", + method = RequestMethod.POST) + public void terminateTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { + throw new UnsupportedException(); + } + + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/executions/latest/stop", + method = RequestMethod.POST) + public SuccessResponse stopTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { + scheduleService.stopTask(scheduleId, taskId); + return Responses.ok(Boolean.TRUE); + } + + @ApiOperation(value = "StartTask", notes = "启动任务") + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/executions/latest/start", + method = RequestMethod.POST) + public SuccessResponse startTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { + scheduleService.startTask(scheduleId, taskId); + return Responses.ok(Boolean.TRUE); + } + + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/executions/latest/rollback", + method = RequestMethod.POST) + public SuccessResponse rollbackTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { + scheduleService.rollbackTask(scheduleId, taskId); + return Responses.ok(Boolean.TRUE); + } + + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/executions/latest/log", + method = RequestMethod.GET) + public SuccessResponse getTaskLog(@PathVariable Long scheduleId, @PathVariable Long taskId, + @RequestParam OdcTaskLogLevel logType) { + return Responses.single(scheduleService.getLog(scheduleId, taskId, logType)); + } + + + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/", method = RequestMethod.GET) + public SuccessResponse detailScheduleTask(@PathVariable Long scheduleId, + @PathVariable Long taskId) { + return Responses.single(scheduleService.detailScheduleTask(scheduleId, taskId)); + } + + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks", method = RequestMethod.GET) + public PaginatedResponse listTask( + @PageableDefault(size = Integer.MAX_VALUE, sort = {"id"}, direction = Direction.DESC) Pageable pageable, + @PathVariable Long scheduleId) { + return Responses.paginated(scheduleService.listScheduleTask(pageable, scheduleId)); + } + + // schedule + + @RequestMapping(value = "/schedules/{id:[\\d]+}/terminate", method = RequestMethod.POST) + public void terminateSchedule(@PathVariable("id") Long id) { + scheduleService.terminate(id); + } + + @RequestMapping(value = "/schedules/{id:[\\d]+}/pause", method = RequestMethod.POST) + public void pauseSchedule(@PathVariable Long id) { + scheduleService.pause(id); + } + + @RequestMapping(value = "/schedules/{id:[\\d]+}/resume", method = RequestMethod.POST) + public void resumeSchedule(@PathVariable Long id) { + scheduleService.resume(id); + } + + @RequestMapping(value = "/schedules/{id:[\\d]+}", method = RequestMethod.PUT) + public void updateSchedule(@PathVariable Long id, @RequestBody UpdateScheduleReq req) { + scheduleService.update(id, req); + } + + @RequestMapping(value = "/schedules", method = RequestMethod.POST) + public void createSchedule(@RequestBody CreateScheduleReq req) { + scheduleService.create(req); + } + + + @RequestMapping("/schedules") + public PaginatedResponse list( @PageableDefault(size = Integer.MAX_VALUE, sort = {"id"}, direction = Direction.DESC) Pageable pageable, @RequestParam(required = false, name = "connectionId") List connectionIds, + @RequestParam(required = false, name = "databaseName") String databaseName, + @RequestParam(required = false, name = "tenantId") String tenantId, + @RequestParam(required = false, name = "clusterId") String clusterId, @RequestParam(required = false, name = "id") Long id, @RequestParam(required = false, name = "status") List status, - @RequestParam(required = false, name = "type") JobType type, + @RequestParam(required = false, name = "type") ScheduleType type, @RequestParam(required = false, name = "startTime") Date startTime, @RequestParam(required = false, name = "endTime") Date endTime, @RequestParam(required = false, name = "creator") String creator, @@ -76,6 +178,9 @@ public PaginatedResponse list( QueryScheduleParams req = QueryScheduleParams.builder() .id(id) .connectionIds(connectionIds) + .databaseName(databaseName) + .tenantId(tenantId) + .clusterId(clusterId) .statuses(status) .type(type) .startTime(startTime) @@ -83,25 +188,13 @@ public PaginatedResponse list( .creator(creator) .projectId(projectId) .build(); - return Responses.paginated(scheduleService.list(pageable, req)); + return Responses.paginated(scheduleService.getScheduleListResp(pageable, req)); } - @RequestMapping(value = "/scheduleConfigs/{id:[\\d]+}", method = RequestMethod.GET) + @RequestMapping(value = "/schedules/{id:[\\d]+}", method = RequestMethod.GET) public SuccessResponse detailSchedule(@PathVariable Long id) { - return Responses.single(scheduleService.getById(id)); - } - - @RequestMapping(value = "/scheduleConfigs/{scheduleId:[\\d]+}/scheduleTask/{scheduleTaskId:[\\d]+}", - method = RequestMethod.GET) - public SuccessResponse detailScheduleTask(@PathVariable Long scheduleId, - @PathVariable Long scheduleTaskId) { - return Responses.single(scheduleService.detailScheduleTask(scheduleId, scheduleTaskId)); - } - - @RequestMapping(value = "/{id:[\\d]+}/jobs/async/batchGetDownloadUrl", method = RequestMethod.POST) - public ListResponse getDownloadUrl(@PathVariable Long id, @RequestBody List objectId) { - return Responses.list(scheduleService.getAsyncDownloadUrl(id, objectId)); + return Responses.single(scheduleService.detailSchedule(id)); } @RequestMapping(value = "/schedules/{id:[\\d]+}/dlmRateLimitConfiguration", method = RequestMethod.PUT) @@ -110,50 +203,4 @@ public SuccessResponse updateLimiterConfig(@PathVariable return Responses.single(dlmLimiterService.updateByOrderId(id, limiterConfig)); } - @ApiOperation(value = "TriggerJob", notes = "立即调度") - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}", method = RequestMethod.POST) - public SuccessResponse triggerJob(@PathVariable Long scheduleId, @RequestParam String jobType) { - return Responses.single(scheduleService.triggerJob(scheduleId, jobType)); - } - - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks", method = RequestMethod.GET) - public PaginatedResponse listTask( - @PageableDefault(size = Integer.MAX_VALUE, sort = {"id"}, direction = Direction.DESC) Pageable pageable, - @PathVariable Long scheduleId) { - return Responses.paginated(scheduleService.listTask(pageable, scheduleId)); - } - - @ApiOperation(value = "StartTask", notes = "启动任务") - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/start", method = RequestMethod.PUT) - public SuccessResponse startTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - return Responses.single(scheduleService.startTask(scheduleId, taskId)); - } - - @ApiOperation(value = "InterruptTask", notes = "中断任务") - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/interrupt", - method = RequestMethod.PUT) - public SuccessResponse interruptTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - return Responses.single(scheduleService.interruptJob(scheduleId, taskId)); - } - - @ApiOperation(value = "PauseTask", notes = "暂停任务") - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/pause", method = RequestMethod.PUT) - public SuccessResponse pauseTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - throw new UnsupportedException(); - } - - @ApiOperation(value = "RollbackTask", notes = "回滚任务") - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/rollback", method = RequestMethod.PUT) - public SuccessResponse rollbackTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - return Responses.single(scheduleService.rollbackTask(scheduleId, taskId)); - } - - - @ApiOperation(value = "GetScheduleTaskLog", notes = "获取计划任务日志") - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/log", method = RequestMethod.GET) - public SuccessResponse getScheduleTaskLog(@PathVariable Long scheduleId, @PathVariable Long taskId, - @RequestParam OdcTaskLogLevel logType) { - return Responses.single(scheduleService.getLog(scheduleId, taskId, logType)); - } - } diff --git a/server/odc-server/src/main/resources/log4j2.xml b/server/odc-server/src/main/resources/log4j2.xml index 32c7e56fa8..0d98b33089 100644 --- a/server/odc-server/src/main/resources/log4j2.xml +++ b/server/odc-server/src/main/resources/log4j2.xml @@ -555,8 +555,8 @@ + fileName="${LOG_DIRECTORY}/scheduleTask/${ctx:scheduleId}-${ctx:scheduleType}/${ctx:scheduleTaskId}/log.all" + filePattern="${LOG_DIRECTORY}/scheduleTask/${ctx:scheduleId}-${ctx:scheduleType}/${ctx:scheduleTaskId}/${date:yyyy-MM}/log-%d{yyyy-MM-dd}-%i.all.gz"> %d{yyyy-MM-dd HH:mm:ss} [%p] %m%n @@ -577,8 +577,8 @@ + fileName="${LOG_DIRECTORY}/scheduleTask/${ctx:scheduleId}-${ctx:scheduleType}/${ctx:scheduleTaskId}/log.warn" + filePattern="${LOG_DIRECTORY}/scheduleTask/${ctx:scheduleId}-${ctx:scheduleType}/${ctx:scheduleTaskId}/${date:yyyy-MM}/log-%d{yyyy-MM-dd}-%i.warn.gz"> %d{yyyy-MM-dd HH:mm:ss} [%p] %m%n diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java new file mode 100644 index 0000000000..3856fc9743 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.metadb.schedule; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/10 17:51 + * @Descripition: + */ + +@Entity +@Data +@Table(name = "schedule_latest_schedule_task_link") +public class LatestScheduleTaskLinkEntity { + + @Id + @Column(name = "id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "schedule_id", nullable = false) + private Long scheduleId; + + @Column(name = "schedule_task_id", nullable = false) + private Long scheduleTaskId; +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java new file mode 100644 index 0000000000..0cd6102e90 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.metadb.schedule; + +import java.util.List; +import java.util.Set; + +import com.oceanbase.odc.config.jpa.OdcJpaRepository; + +/** + * @Author:tinker + * @Date: 2024/6/10 18:58 + * @Descripition: + */ +public interface LatestScheduleTaskLinkRepository extends OdcJpaRepository { + + Long getScheduleTaskIdByScheduleId(Long scheduleId); + + List findByScheduleIdIn(Set scheduleIds); +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java new file mode 100644 index 0000000000..153f51104d --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.oceanbase.odc.metadb.schedule; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.oceanbase.odc.service.schedule.model.OperationType; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeStatus; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/5/28 15:10 + * @Descripition: + */ +@Entity +@Data +@Table(name = "schedule_change_log") +public class ScheduleChangeLogEntity { + + @Id + @Column(name = "id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "schedule_id", nullable = false) + private Long scheduleId; + + @Column(name = "flow_instance_id") + private Long flowInstanceId; + + @Column(name = "old_schedule_parameters") + private String oldScheduleParameterJson; + + @Column(name = "new_schedule_parameters") + private String newScheduleParameterJson; + + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) + private ScheduleChangeStatus status; + + @Enumerated(EnumType.STRING) + @Column(name = "type", nullable = false) + private OperationType type; + + @Column(name = "create_time", insertable = false, updatable = false) + private Date createTime; + + @Column(name = "update_time", insertable = false, updatable = false) + private Date updateTime; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepository.java new file mode 100644 index 0000000000..0bbc1f816d --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepository.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.metadb.schedule; + +import java.util.List; +import java.util.Optional; + +import com.oceanbase.odc.config.jpa.OdcJpaRepository; + +/** + * @Author:tinker + * @Date: 2024/6/8 15:27 + * @Descripition: + */ +public interface ScheduleChangeLogRepository extends OdcJpaRepository { + + List findByScheduleId(Long scheduleId); + + Optional findByIdAndScheduleId(Long id, Long scheduleId); + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java index 81ec13598b..6b6155b97e 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java @@ -31,8 +31,8 @@ import org.hibernate.annotations.GenerationTime; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; -import com.oceanbase.odc.service.schedule.model.JobType; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import lombok.Data; @@ -74,7 +74,7 @@ public class ScheduleEntity implements Serializable { @Enumerated(EnumType.STRING) @Column(name = "job_type", nullable = false) - private JobType jobType; + private ScheduleType scheduleType; @Column(name = "job_parameters_json", nullable = false) private String jobParametersJson; @Column(name = "trigger_config_json", nullable = false) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java index cc32084cd6..aa5505ebc4 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java @@ -55,9 +55,8 @@ public interface ScheduleRepository extends OdcJpaRepository find(@NotNull Pageable pageable, @NotNull QueryScheduleParams params) { Specification specification = Specification .where(OdcJpaRepository.between(ScheduleEntity_.createTime, params.getStartTime(), params.getEndTime())) - .and(OdcJpaRepository.eq(ScheduleEntity_.jobType, params.getType())) + .and(OdcJpaRepository.eq(ScheduleEntity_.scheduleType, params.getType())) .and(OdcJpaRepository.in(ScheduleEntity_.projectId, params.getProjectIds())) - .and(OdcJpaRepository.in(ScheduleEntity_.creatorId, params.getCreatorIds())) .and(OdcJpaRepository.eq(ScheduleEntity_.id, params.getId())) .and(OdcJpaRepository.in(ScheduleEntity_.status, params.getStatuses())) .and(OdcJpaRepository.eq(ScheduleEntity_.organizationId, params.getOrganizationId())); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java index 16ee8fe974..548058aaee 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java @@ -16,6 +16,8 @@ package com.oceanbase.odc.metadb.schedule; import java.util.List; +import java.util.Optional; +import java.util.Set; import javax.transaction.Transactional; @@ -37,6 +39,8 @@ public interface ScheduleTaskRepository extends JpaRepository, JpaSpecificationExecutor { + Optional findByIdAndJobName(Long id, Long scheduleId); + List findByJobNameAndStatusIn(String jobName, List statuses); @Transactional @@ -71,6 +75,10 @@ public interface ScheduleTaskRepository extends JpaRepository findByJobId(Long jobId); + @Query(value = "select st.* from ScheduleTaskEntity st where st.jobName in (:jobNames)", nativeQuery = true) + List findByJobNames(@Param("jobNames") Set jobNames); + + @Transactional @Modifying @Query("update ScheduleTaskEntity st set st.parametersJson=:#{#entity.parametersJson}," diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java index 524e59d26d..c27f87c19b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java @@ -19,7 +19,8 @@ import java.util.List; import java.util.Set; -import com.oceanbase.odc.core.flow.model.TaskParameters; +import com.oceanbase.odc.service.connection.database.model.Database; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskParameters; import com.oceanbase.tools.dbbrowser.model.DBObjectType; import com.oceanbase.tools.migrator.common.enums.MigrationInsertAction; import com.oceanbase.tools.migrator.common.enums.ShardingStrategy; @@ -32,7 +33,7 @@ * @Descripition: */ @Data -public class DataArchiveParameters implements TaskParameters { +public class DataArchiveParameters implements ScheduleTaskParameters { private String name; @@ -40,13 +41,11 @@ public class DataArchiveParameters implements TaskParameters { private Long targetDataBaseId; - private String sourceDatabaseName; + // inner init + private Database sourceDatabase; - private String targetDatabaseName; - - private String sourceDataSourceName; - - private String targetDataSourceName; + // inner init + private Database targetDatabase; private List variables; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java index 37695f951c..6739f7ae7a 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java @@ -17,7 +17,8 @@ import java.util.List; -import com.oceanbase.odc.core.flow.model.TaskParameters; +import com.oceanbase.odc.service.connection.database.model.Database; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskParameters; import lombok.Data; @@ -27,19 +28,17 @@ * @Descripition: */ @Data -public class DataDeleteParameters implements TaskParameters { +public class DataDeleteParameters implements ScheduleTaskParameters { private Long databaseId; - private String databaseName; - private Long targetDatabaseId; - private String targetDatabaseName; - - private String sourceDataSourceName; + // inner init + private Database database; - private String targetDataSourceName; + // inner init + private Database targetDatabase; private List variables; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java index a2468099eb..03f4244b9b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java @@ -30,4 +30,17 @@ public class OffsetConfig { private String pattern; + private String dateFormatPattern; + + private Operator operator; + + private String unit; + + private String value; +} + + +enum Operator { + PLUS, + MINUS } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java index 23d29a3bd8..8ad2c6cfed 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java @@ -90,7 +90,6 @@ import com.oceanbase.odc.metadb.flow.UserTaskInstanceEntity; import com.oceanbase.odc.metadb.flow.UserTaskInstanceRepository; import com.oceanbase.odc.metadb.iam.resourcerole.ResourceRoleEntity; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.metadb.task.TaskEntity; import com.oceanbase.odc.plugin.task.api.datatransfer.model.DataTransferConfig; import com.oceanbase.odc.service.collaboration.environment.EnvironmentService; @@ -110,8 +109,6 @@ import com.oceanbase.odc.service.dispatch.DispatchResponse; import com.oceanbase.odc.service.dispatch.RequestDispatcher; import com.oceanbase.odc.service.dispatch.TaskDispatchChecker; -import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; -import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; import com.oceanbase.odc.service.flow.factory.FlowFactory; import com.oceanbase.odc.service.flow.factory.FlowResponseMapperFactory; import com.oceanbase.odc.service.flow.instance.BaseFlowNodeInstance; @@ -166,11 +163,6 @@ import com.oceanbase.odc.service.regulation.risklevel.RiskLevelService; import com.oceanbase.odc.service.regulation.risklevel.model.RiskLevel; import com.oceanbase.odc.service.regulation.risklevel.model.RiskLevelDescriber; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.flowtask.AlterScheduleParameters; -import com.oceanbase.odc.service.schedule.flowtask.OperationType; -import com.oceanbase.odc.service.schedule.model.JobType; -import com.oceanbase.odc.service.schedule.model.ScheduleStatus; import com.oceanbase.odc.service.task.TaskService; import com.oceanbase.odc.service.task.model.ExecutorInfo; @@ -225,8 +217,6 @@ public class FlowInstanceService { @Qualifier("autoApprovalExecutor") private ThreadPoolTaskExecutor executorService; @Autowired - private ScheduleService scheduleService; - @Autowired private ApprovalClient approvalClient; @Autowired private IntegrationService integrationService; @@ -328,20 +318,7 @@ public List create(@NotNull @Valid CreateFlowInstanceReq } private List innerCreate(@NotNull @Valid CreateFlowInstanceReq createReq) { - // TODO 原终止逻辑想表达的语意是终止执行中的计划,但目前线上的语意是终止审批流。暂保留逻辑,待前端修改后删除。 checkCreateFlowInstancePermission(createReq); - if (createReq.getTaskType() == TaskType.ALTER_SCHEDULE) { - AlterScheduleParameters parameters = (AlterScheduleParameters) createReq.getParameters(); - if (parameters.getOperationType() == OperationType.TERMINATION) { - ScheduleEntity scheduleEntity = scheduleService.nullSafeGetById(parameters.getTaskId()); - if (scheduleEntity.getStatus() == ScheduleStatus.APPROVING) { - Set flowInstanceIds = getApprovingAlterScheduleById(scheduleEntity.getId()); - return flowInstanceIds.stream().map(id -> cancel(id, false)) - .collect(Collectors.toList()); - } - return Collections.emptyList(); - } - } if (createReq.getTaskType() == TaskType.ASYNC) { DatabaseChangeParameters taskParameters = (DatabaseChangeParameters) createReq.getParameters(); PreConditions.maxLength(taskParameters.getSqlContent(), "sql content", @@ -554,7 +531,6 @@ public FlowInstanceDetailResp detail(@NotNull Long id) { @Transactional(rollbackFor = Exception.class) public FlowInstanceDetailResp cancel(@NotNull Long id, Boolean skipAuth) { FlowInstance flowInstance = mapFlowInstance(id, flowInst -> flowInst, skipAuth); - scheduleService.updateStatusByFlowInstanceId(id, ScheduleStatus.TERMINATION); return cancel(flowInstance, skipAuth); } @@ -702,7 +678,6 @@ public FlowInstanceDetailResp reject(@NotNull Long id, flowInstanceRepository.updateStatusById(instance.getFlowInstanceId(), FlowStatus.REJECTED); }, skipAuth); - scheduleService.updateStatusByFlowInstanceId(id, ScheduleStatus.REJECTED); Optional optional = flowFactory.getFlowInstance(id); FlowInstance flowInstance = optional.orElseThrow(() -> new NotFoundException(ResourceType.ODC_FLOW_INSTANCE, "id", id)); @@ -759,33 +734,7 @@ private void checkCreateFlowInstancePermission(CreateFlowInstanceReq req) { databaseIds.add(req.getDatabaseId()); } TaskType taskType = req.getTaskType(); - if (taskType == TaskType.ALTER_SCHEDULE) { - AlterScheduleParameters params = (AlterScheduleParameters) req.getParameters(); - // Check the new parameters during creation or update. - if (params.getOperationType() == OperationType.CREATE - || params.getOperationType() == OperationType.UPDATE) { - if (params.getType() == JobType.DATA_ARCHIVE) { - DataArchiveParameters p = (DataArchiveParameters) params.getScheduleTaskParameters(); - databaseIds.add(p.getSourceDatabaseId()); - databaseIds.add(p.getTargetDataBaseId()); - } else if (params.getType() == JobType.DATA_DELETE) { - DataDeleteParameters p = (DataDeleteParameters) params.getScheduleTaskParameters(); - databaseIds.add(p.getDatabaseId()); - } - } else { - ScheduleEntity scheduleEntity = scheduleService.nullSafeGetById(params.getTaskId()); - if (params.getType() == JobType.DATA_ARCHIVE) { - DataArchiveParameters p = JsonUtils.fromJson(scheduleEntity.getJobParametersJson(), - DataArchiveParameters.class); - databaseIds.add(p.getSourceDatabaseId()); - databaseIds.add(p.getTargetDataBaseId()); - } else if (params.getType() == JobType.DATA_DELETE) { - DataDeleteParameters p = JsonUtils.fromJson(scheduleEntity.getJobParametersJson(), - DataDeleteParameters.class); - databaseIds.add(p.getDatabaseId()); - } - } - } else if (taskType == TaskType.STRUCTURE_COMPARISON) { + if (taskType == TaskType.STRUCTURE_COMPARISON) { DBStructureComparisonParameter p = (DBStructureComparisonParameter) req.getParameters(); databaseIds.add(p.getTargetDatabaseId()); databaseIds.add(p.getSourceDatabaseId()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/listener/PreCheckServiceTaskFailedListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/listener/PreCheckServiceTaskFailedListener.java index d102adc0d6..c31a2a1ac1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/listener/PreCheckServiceTaskFailedListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/listener/PreCheckServiceTaskFailedListener.java @@ -26,8 +26,6 @@ import com.oceanbase.odc.service.flow.FlowableAdaptor; import com.oceanbase.odc.service.flow.instance.FlowTaskInstance; import com.oceanbase.odc.service.flow.model.FlowNodeStatus; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.ScheduleStatus; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; @@ -44,8 +42,6 @@ public class PreCheckServiceTaskFailedListener extends BaseStatusModifyListener< private FlowInstanceRepository flowInstanceRepository; @Autowired private ServiceTaskInstanceRepository serviceTaskRepository; - @Autowired - private ScheduleService scheduleService; @Override protected FlowNodeStatus doModifyStatusOnStart(FlowTaskInstance target) { @@ -63,7 +59,6 @@ protected FlowNodeStatus doModifyStatusOnEnd(FlowTaskInstance target) { flowInstanceRepository.updateStatusById(target.getFlowInstanceId(), FlowStatus.PRE_CHECK_FAILED); FlowNodeStatus status = FlowNodeStatus.FAILED; int affectRows = serviceTaskRepository.updateStatusById(target.getId(), status); - scheduleService.updateStatusByFlowInstanceId(target.getFlowInstanceId(), ScheduleStatus.TERMINATION); log.info("Modify node instance status successfully, instanceId={}, instanceType={}, affectRows={}", target.getId(), target.getNodeType(), affectRows); return status; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/CreateFlowInstanceProcessAspect.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/CreateFlowInstanceProcessAspect.java index 3c5ee9e0b2..1fce17332d 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/CreateFlowInstanceProcessAspect.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/CreateFlowInstanceProcessAspect.java @@ -28,23 +28,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.oceanbase.odc.core.shared.PreConditions; import com.oceanbase.odc.core.shared.constant.OrganizationType; import com.oceanbase.odc.core.shared.constant.TaskType; import com.oceanbase.odc.core.shared.exception.BadRequestException; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.plugin.task.api.datatransfer.model.DataTransferConfig; -import com.oceanbase.odc.service.collaboration.project.ProjectService; import com.oceanbase.odc.service.connection.database.DatabaseService; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; import com.oceanbase.odc.service.flow.task.model.DBStructureComparisonParameter; import com.oceanbase.odc.service.flow.util.DescriptionGenerator; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.flowtask.AlterScheduleParameters; -import com.oceanbase.odc.service.schedule.flowtask.OperationType; -import com.oceanbase.odc.service.schedule.model.JobType; import lombok.extern.slf4j.Slf4j; @@ -64,13 +57,7 @@ public class CreateFlowInstanceProcessAspect implements InitializingBean { @Autowired private AuthenticationFacade authenticationFacade; @Autowired - private ScheduleService scheduleService; - @Autowired private List preprocessors; - @Autowired - private ProjectService projectService; - - private final Map scheduleTaskPreprocessors = new HashMap<>(); private final Map flowTaskPreprocessors = new HashMap<>(); @@ -92,12 +79,6 @@ public void preprocess(JoinPoint point) throws Throwable { if (flowTaskPreprocessors.containsKey(req.getTaskType())) { flowTaskPreprocessors.get(req.getTaskType()).process(req); } - } else { - AlterScheduleParameters parameters = (AlterScheduleParameters) req.getParameters(); - authenticateOperation(parameters); - if (scheduleTaskPreprocessors.containsKey(parameters.getType())) { - scheduleTaskPreprocessors.get(parameters.getType()).process(req); - } } } @@ -116,31 +97,9 @@ public void afterPropertiesSet() throws Exception { flowTaskPreprocessors.put(annotation.type(), preprocessor); } } - // Init schedule task processor. - if (preprocessor.getClass().isAnnotationPresent(ScheduleTaskPreprocessor.class)) { - ScheduleTaskPreprocessor annotation = - preprocessor.getClass().getAnnotation(ScheduleTaskPreprocessor.class); - if (annotation.isEnabled()) { - if (scheduleTaskPreprocessors.containsKey(annotation.type())) { - throw new RuntimeException( - String.format("The processor has already been defined,type=%s", annotation.type())); - } - scheduleTaskPreprocessors.put(annotation.type(), preprocessor); - } - } }); } - private void authenticateOperation(AlterScheduleParameters parameters) { - if (parameters.getOperationType() == OperationType.CREATE) { - return; - } - PreConditions.notNull(parameters.getTaskId(), "scheduleId"); - ScheduleEntity scheduleEntity = - scheduleService.nullSafeGetByIdWithCheckPermission(parameters.getTaskId(), true); - parameters.setType(scheduleEntity.getJobType()); - } - /** * get connectionId and projectId from database. */ diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java index ed7480e91b..c31df2c2f1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/ResultSetExportPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java similarity index 94% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/ResultSetExportPreprocessor.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java index c76c03bed9..2e12aa837f 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/ResultSetExportPreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.oceanbase.odc.service.schedule.flowtask; +package com.oceanbase.odc.service.flow.processor; import java.util.List; import java.util.regex.Pattern; @@ -31,8 +31,6 @@ import com.oceanbase.odc.service.connection.ConnectionService; import com.oceanbase.odc.service.connection.model.ConnectionConfig; import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; -import com.oceanbase.odc.service.flow.processor.FlowTaskPreprocessor; -import com.oceanbase.odc.service.flow.processor.Preprocessor; import com.oceanbase.odc.service.resultset.ResultSetExportTaskParameter; import com.oceanbase.tools.dbbrowser.parser.ParserUtil; import com.oceanbase.tools.dbbrowser.parser.constant.GeneralSqlType; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/DatabaseChangeParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/DatabaseChangeParameters.java index 869ecc135f..c3cfb399ff 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/DatabaseChangeParameters.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/DatabaseChangeParameters.java @@ -22,7 +22,7 @@ import com.oceanbase.odc.core.flow.model.TaskParameters; import com.oceanbase.odc.core.shared.constant.TaskErrorStrategy; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import lombok.Data; @@ -49,7 +49,7 @@ public class DatabaseChangeParameters implements Serializable, TaskParameters { private Boolean generateRollbackPlan; private boolean modifyTimeoutIfTimeConsumingSqlExists = true; // internal usage for notification - private JobType parentJobType; + private ScheduleType parentScheduleType; private Integer retryTimes = 0; private Long retryIntervalMillis = 180000L; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/OnlineSchemaChangeTaskResult.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/OnlineSchemaChangeTaskResult.java index 4315b0330c..440653f21b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/OnlineSchemaChangeTaskResult.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/OnlineSchemaChangeTaskResult.java @@ -18,7 +18,7 @@ import java.util.List; import com.oceanbase.odc.core.flow.model.AbstractFlowTaskResult; -import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; +import com.oceanbase.odc.service.schedule.model.ScheduleTask; import lombok.AllArgsConstructor; import lombok.Data; @@ -30,5 +30,5 @@ @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class OnlineSchemaChangeTaskResult extends AbstractFlowTaskResult { - private List tasks; + private List tasks; } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java index 3752ec38ed..047a04c691 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java @@ -81,7 +81,7 @@ import com.oceanbase.odc.service.permission.database.model.ApplyDatabaseParameter.ApplyDatabase; import com.oceanbase.odc.service.permission.project.ApplyProjectParameter; import com.oceanbase.odc.service.schedule.flowtask.AlterScheduleParameters; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleTask; import lombok.extern.slf4j.Slf4j; @@ -170,15 +170,15 @@ public Event ofRejectedTask(TaskEntity task, Long approver) { return event; } - public Event ofSucceededTask(ScheduleEntity schedule) { - Event event = ofSchedule(schedule, TaskEvent.EXECUTION_SUCCEEDED); - resolveLabels(event.getLabels(), schedule); + public Event ofSucceededTask(ScheduleTask scheduleTask) { + Event event = ofScheduleTask(scheduleTask, TaskEvent.EXECUTION_SUCCEEDED); + resolveLabels(event.getLabels(), scheduleTask); return event; } - public Event ofFailedTask(ScheduleEntity schedule) { - Event event = ofSchedule(schedule, TaskEvent.EXECUTION_FAILED); - resolveLabels(event.getLabels(), schedule); + public Event ofFailedTask(ScheduleTask scheduleTask) { + Event event = ofScheduleTask(scheduleTask, TaskEvent.EXECUTION_FAILED); + resolveLabels(event.getLabels(), scheduleTask); return event; } @@ -242,23 +242,45 @@ private Event ofTask(TaskEntity task, TaskEvent status) { .build(); } + + private Event ofScheduleTask(ScheduleTask scheduleTask, TaskEvent status) { + + ScheduleEntity schedule = scheduleRepository.findById(Long.valueOf(scheduleTask.getJobName())).get(); + EventLabels labels = new EventLabels(); + labels.putIfNonNull(TASK_STATUS, status.name()); + labels.putIfNonNull(TRIGGER_TIME, LocalDateTime.now().format(DATE_FORMATTER)); + labels.putIfNonNull(REGION, OB_ARN_PARTITION); + labels.putIfNonNull(DESCRIPTION, schedule.getDescription()); + + labels.putIfNonNull(TASK_TYPE, scheduleTask.getJobGroup()); + + labels.putIfNonNull(TASK_ID, schedule.getId()); + labels.putIfNonNull(CONNECTION_ID, schedule.getConnectionId()); + labels.putIfNonNull(CREATOR_ID, schedule.getCreatorId()); + labels.putIfNonNull(PROJECT_ID, schedule.getProjectId()); + labels.putIfNonNull(DATABASE_ID, schedule.getDatabaseId()); + labels.putIfNonNull(DATABASE_NAME, schedule.getDatabaseName()); + + return Event.builder() + .status(EventStatus.CREATED) + .creatorId(schedule.getCreatorId()) + .organizationId(schedule.getOrganizationId()) + .projectId(schedule.getProjectId()) + .triggerTime(new Date()) + .labels(labels) + .build(); + } + + private Event ofSchedule(ScheduleEntity schedule, TaskEvent status) { + EventLabels labels = new EventLabels(); labels.putIfNonNull(TASK_STATUS, status.name()); labels.putIfNonNull(TRIGGER_TIME, LocalDateTime.now().format(DATE_FORMATTER)); labels.putIfNonNull(REGION, OB_ARN_PARTITION); labels.putIfNonNull(DESCRIPTION, schedule.getDescription()); - switch (schedule.getJobType()) { - case DATA_ARCHIVE: - case DATA_ARCHIVE_DELETE: - case DATA_ARCHIVE_ROLLBACK: - labels.putIfNonNull(TASK_TYPE, JobType.DATA_ARCHIVE); - break; - default: - labels.putIfNonNull(TASK_TYPE, schedule.getJobType()); - break; - } + labels.putIfNonNull(TASK_TYPE, schedule.getScheduleType()); labels.putIfNonNull(TASK_ID, schedule.getId()); labels.putIfNonNull(CONNECTION_ID, schedule.getConnectionId()); labels.putIfNonNull(CREATOR_ID, schedule.getCreatorId()); @@ -326,8 +348,8 @@ private void resolveLabels(EventLabels labels, T task) { if (taskEntity.getTaskType() == TaskType.ASYNC) { DatabaseChangeParameters parameters = JsonUtils.fromJson(taskEntity.getParametersJson(), DatabaseChangeParameters.class); - if (Objects.nonNull(parameters.getParentJobType())) { - labels.putIfNonNull(TASK_TYPE, parameters.getParentJobType()); + if (Objects.nonNull(parameters.getParentScheduleType())) { + labels.putIfNonNull(TASK_TYPE, parameters.getParentScheduleType()); labels.putIfNonNull(TASK_ID, parentInstanceId); } else { labels.putIfNonNull(TASK_ID, flowInstances.get(0).getId()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java index ee655ac7b9..3e37b43408 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java @@ -54,6 +54,8 @@ import com.oceanbase.odc.service.schedule.ScheduleTaskService; import com.oceanbase.odc.service.schedule.model.JobType; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; +import com.oceanbase.odc.service.schedule.model.ScheduleTask; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import com.oceanbase.odc.service.schedule.model.TriggerStrategy; import com.oceanbase.odc.service.task.TaskService; @@ -167,7 +169,7 @@ protected void onTimeout(Long taskId, TaskService taskService) { @Override protected void onProgressUpdate(Long taskId, TaskService taskService) { try { - Page tasks = scheduleTaskService.listTask(Pageable.unpaged(), scheduleId); + Page tasks = scheduleTaskService.list(Pageable.unpaged(), scheduleId); if (tasks.getSize() == 0) { log.info("List schedule task size is 0 by scheduleId {}.", scheduleId); return; @@ -181,7 +183,7 @@ protected void onProgressUpdate(Long taskId, TaskService taskService) { TaskStatus dbStatus = flowTask.getStatus(); Set currentManualSwapTableEnableTasks = new HashSet<>(); - for (ScheduleTaskEntity task : tasks) { + for (ScheduleTask task : tasks) { OnlineSchemaChangeScheduleTaskResult result = JsonUtils.fromJson(task.getResultJson(), OnlineSchemaChangeScheduleTaskResult.class); if (result.isManualSwapTableEnabled()) { @@ -208,12 +210,12 @@ protected void onProgressUpdate(Long taskId, TaskService taskService) { } - private void progressStatusUpdate(Page tasks) { + private void progressStatusUpdate(Page tasks) { int successfulTask = 0; int failedTask = 0; boolean canceled = false; - for (ScheduleTaskEntity task : tasks) { + for (ScheduleTask task : tasks) { TaskStatus taskStatus = task.getStatus(); if (taskStatus == TaskStatus.DONE) { successfulTask++; @@ -233,7 +235,7 @@ private void progressStatusUpdate(Page tasks) { } } - private double singleTaskPercentage(ScheduleTaskEntity scheduleTask) { + private double singleTaskPercentage(ScheduleTask scheduleTask) { double percentage; switch (scheduleTask.getStatus()) { case PREPARING: @@ -251,7 +253,7 @@ private double singleTaskPercentage(ScheduleTaskEntity scheduleTask) { @Override protected boolean cancel(boolean mayInterruptIfRunning, Long taskId, TaskService taskService) { - Optional runningEntity = scheduleTaskService.listTask(Pageable.unpaged(), scheduleId) + Optional runningEntity = scheduleTaskService.list(Pageable.unpaged(), scheduleId) .stream().filter(task -> task.getStatus() == TaskStatus.RUNNING) .findFirst(); runningEntity.ifPresent(scheduleTask -> taskHandler.terminate(scheduleId, scheduleTask.getId())); @@ -270,7 +272,7 @@ private ScheduleEntity createScheduleEntity(ConnectionConfig connectionConfig, ScheduleEntity scheduleEntity = new ScheduleEntity(); scheduleEntity.setConnectionId(connectionConfig.id()); scheduleEntity.setDatabaseName(schema); - scheduleEntity.setJobType(JobType.ONLINE_SCHEMA_CHANGE_COMPLETE); + scheduleEntity.setScheduleType(ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE); scheduleEntity.setStatus(ScheduleStatus.ENABLED); scheduleEntity.setAllowConcurrent(false); scheduleEntity.setCreatorId(creatorId); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java index 516d5443a0..5a18446396 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java @@ -53,7 +53,7 @@ import com.oceanbase.odc.service.onlineschemachange.model.OscSwapTableVO; import com.oceanbase.odc.service.onlineschemachange.model.SwapTableType; import com.oceanbase.odc.service.onlineschemachange.rename.OscDBUserUtil; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.session.factory.DefaultConnectSessionFactory; import lombok.NonNull; @@ -134,8 +134,8 @@ public OscSwapTableVO swapTable(@PathVariable Long scheduleTaskId) { OnlineSchemaChangeScheduleTaskResult.class); PreConditions.validArgumentState( - scheduleEntity.get().getJobType() == JobType.ONLINE_SCHEMA_CHANGE_COMPLETE, - ErrorCodes.BadArgument, new Object[] {scheduleEntity.get().getJobType()}, + scheduleEntity.get().getScheduleType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE, + ErrorCodes.BadArgument, new Object[] {scheduleEntity.get().getScheduleType()}, "Task type is not " + TaskType.ONLINE_SCHEMA_CHANGE.name()); SwapTableType swapTableType = oscParameters.getSwapTableType(); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java index e1c6f634f7..66957abfb6 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java @@ -55,8 +55,8 @@ import com.oceanbase.odc.service.partitionplan.model.PartitionPlanTableConfig; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.JobType; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import lombok.NonNull; @@ -246,7 +246,7 @@ public void disablePartitionPlanTables(@NonNull List partitionPlanTableIds Set scheduleIds = ppts.stream().map(PartitionPlanTableEntity::getScheduleId) .collect(Collectors.toSet()); for (Long scheduleId : scheduleIds) { - scheduleService.terminate(scheduleService.nullSafeGetById(scheduleId)); + // scheduleService.changeSchedule(scheduleService.nullSafeGetById(scheduleId)); } log.info("Disable partition plan related tables succeed, ids={}, tableNames={}", pptIds, ppts.stream() .map(PartitionPlanTableEntity::getTableName).collect(Collectors.toList())); @@ -259,7 +259,7 @@ private ScheduleEntity createAndEnableSchedule(Database database, @NonNull Trigg scheduleEntity.setStatus(ScheduleStatus.ENABLED); scheduleEntity.setAllowConcurrent(false); scheduleEntity.setMisfireStrategy(MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING); - scheduleEntity.setJobType(JobType.PARTITION_PLAN); + scheduleEntity.setScheduleType(ScheduleType.PARTITION_PLAN); scheduleEntity.setTriggerConfigJson(JsonUtils.toJson(triggerConfig)); scheduleEntity.setProjectId(database.getProject().getId()); scheduleEntity.setConnectionId(database.getDataSource().getId()); @@ -267,8 +267,8 @@ private ScheduleEntity createAndEnableSchedule(Database database, @NonNull Trigg scheduleEntity.setCreatorId(this.authenticationFacade.currentUserId()); scheduleEntity.setModifierId(this.authenticationFacade.currentUserId()); scheduleEntity.setOrganizationId(this.authenticationFacade.currentOrganizationId()); - scheduleEntity = this.scheduleService.create(scheduleEntity); - this.scheduleService.enable(scheduleEntity); + // scheduleEntity = this.scheduleService.create(scheduleEntity); + // this.scheduleService.enable(scheduleEntity); return scheduleEntity; } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java index 8d4a5ae6cb..8d1175c88d 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java @@ -15,10 +15,7 @@ */ package com.oceanbase.odc.service.quartz; -import java.util.List; import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -40,13 +37,10 @@ import com.oceanbase.odc.service.iam.UserService; import com.oceanbase.odc.service.iam.model.User; import com.oceanbase.odc.service.iam.util.SecurityContextUtils; -import com.oceanbase.odc.service.notification.Broker; -import com.oceanbase.odc.service.notification.NotificationProperties; -import com.oceanbase.odc.service.notification.helper.EventBuilder; import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; import com.oceanbase.odc.service.schedule.flowtask.ScheduleTaskContextHolder; -import com.oceanbase.odc.service.schedule.model.JobType; -import com.oceanbase.odc.service.task.config.TaskFrameworkEnabledProperties; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskType; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.task.model.ExecutorInfo; import lombok.extern.slf4j.Slf4j; @@ -69,14 +63,7 @@ public class OdcJobListener implements JobListener { private UserService userService; @Autowired private HostProperties hostProperties; - @Autowired - private Broker broker; - @Autowired - private EventBuilder eventBuilder; - @Autowired - private NotificationProperties notificationProperties; - @Autowired - private TaskFrameworkEnabledProperties taskFrameworkEnabledProperties; + private static final String ODC_JOB_LISTENER = "ODC_JOB_LISTENER"; @Override @@ -90,7 +77,8 @@ public String getName() { @Override public void jobToBeExecuted(JobExecutionContext context) { // todo skip osc task - if (Objects.equals(context.getJobDetail().getKey().getGroup(), JobType.ONLINE_SCHEMA_CHANGE_COMPLETE.name())) { + if (Objects.equals(context.getJobDetail().getKey().getGroup(), + ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE.name())) { return; } // Init user. @@ -98,36 +86,11 @@ public void jobToBeExecuted(JobExecutionContext context) { ScheduleEntity scheduleEntity = scheduleRepository.findById(scheduleId) .orElseThrow(() -> new NotFoundException(ResourceType.ODC_SCHEDULE, "id", scheduleId)); - ScheduleTaskContextHolder.trace(scheduleEntity.getId(), scheduleEntity.getJobType().name(), null); + ScheduleTaskContextHolder.trace(scheduleEntity.getId(), scheduleEntity.getScheduleType().name(), null); log.info("Job to be executed.OrganizationId={},ProjectId={},DatabaseId={},JobType={}", scheduleEntity.getOrganizationId(), scheduleEntity.getProjectId(), scheduleEntity.getDatabaseId(), - scheduleEntity.getJobType()); - // For tasks that do not allow concurrent execution, if they can be successfully scheduled, it - // indicates that the existing tasks have exited. If there are still tasks in the processing state, - // then it is necessary to correct their status. - if (context.getJobDetail().isConcurrentExectionDisallowed() && scheduleEntity.getJobType().isSync()) { - List toBeCorrectedList = taskRepository.findByJobNameAndStatusIn( - scheduleId.toString(), TaskStatus.getProcessingStatus()); - // For the scenario where the task framework is switched from closed to open, it is necessary to - // correct - // the status of tasks that were not completed while in the closed state. - if (taskFrameworkEnabledProperties.isEnabled()) { - toBeCorrectedList = - toBeCorrectedList.stream().filter(o -> o.getJobId() == null).collect(Collectors.toList()); - } - toBeCorrectedList.forEach(task -> { - taskRepository.updateStatusById(task.getId(), TaskStatus.CANCELED); - log.info("Task status correction successful,scheduleTaskId={}", task.getId()); - }); - } - // Ignore this schedule if scheduler has executing job. - if (taskFrameworkEnabledProperties.isEnabled() && scheduleEntity.getJobType().executeInTaskFramework() - && !scheduleEntity.getAllowConcurrent() - && !taskRepository.findByJobNameAndStatusIn(scheduleId.toString(), TaskStatus.getProcessingStatus()) - .isEmpty()) { - log.warn("Concurrent is not allowed for scheduler {}.", scheduleId); - return; - } + scheduleEntity.getScheduleType()); + UserEntity userEntity = userService.nullSafeGet(scheduleEntity.getCreatorId()); userEntity.setOrganizationId(scheduleEntity.getOrganizationId()); User taskCreator = new User(userEntity); @@ -142,8 +105,8 @@ public void jobToBeExecuted(JobExecutionContext context) { log.info("Create new task from job,jobKey={}", key); entity.setJobName(key.getName()); entity.setJobGroup(key.getGroup()); - if (key.getGroup().equals(JobType.DATA_ARCHIVE_DELETE.name()) - || key.getGroup().equals(JobType.DATA_ARCHIVE_ROLLBACK.name())) { + if (key.getGroup().equals(ScheduleTaskType.DATA_ARCHIVE_DELETE.name()) + || key.getGroup().equals(ScheduleTaskType.DATA_ARCHIVE_ROLLBACK.name())) { entity.setParametersJson(JsonUtils.toJson(context.getJobDetail().getJobDataMap())); } else { entity.setParametersJson(scheduleEntity.getJobParametersJson()); @@ -170,21 +133,5 @@ public void jobExecutionVetoed(JobExecutionContext context) { @Override public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { ScheduleTaskContextHolder.clear(); - Optional scheduleEntityOptional = - scheduleRepository.findById(ScheduleTaskUtils.getScheduleId(context)); - if (notificationProperties.isEnabled() && scheduleEntityOptional.isPresent()) { - try { - ScheduleEntity scheduleEntity = scheduleEntityOptional.get(); - if (jobException != null) { - broker.enqueueEvent(eventBuilder.ofFailedTask(scheduleEntity)); - } else if (!taskFrameworkEnabledProperties.isEnabled() - && scheduleEntity.getJobType().executeInTaskFramework()) { - // only create event for DLM jobs when task framework not enabled to avoid duplicate events - broker.enqueueEvent(eventBuilder.ofSucceededTask(scheduleEntity)); - } - } catch (Exception e) { - log.warn("Failed to enqueue event.", e); - } - } } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcTriggerListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcTriggerListener.java index a65c18ddbe..d7800110d9 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcTriggerListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcTriggerListener.java @@ -31,7 +31,6 @@ import com.oceanbase.odc.service.notification.NotificationProperties; import com.oceanbase.odc.service.notification.helper.EventBuilder; import com.oceanbase.odc.service.notification.model.Event; -import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; import com.oceanbase.odc.service.schedule.ScheduleService; import lombok.extern.slf4j.Slf4j; @@ -62,7 +61,7 @@ public String getName() { @Override public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) { return SpringContextUtil.getBean(ScheduleService.class) - .terminateIfScheduleInvalid(ScheduleTaskUtils.getScheduleId(context)); + .terminateIfScheduleInvalid(Long.parseLong(context.getTrigger().getJobKey().getName())); } @Override diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java index fa6682cae6..fb6d7d0f6c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java @@ -37,11 +37,13 @@ import org.springframework.stereotype.Service; import com.oceanbase.odc.core.authority.util.SkipAuthorize; +import com.oceanbase.odc.core.shared.exception.UnexpectedException; import com.oceanbase.odc.core.shared.exception.UnsupportedException; import com.oceanbase.odc.service.quartz.executor.QuartzJob; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; import com.oceanbase.odc.service.quartz.util.QuartzCronExpressionUtils; import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; +import com.oceanbase.odc.service.schedule.model.QuartzJobChangeReq; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.TriggerConfig; @@ -59,25 +61,64 @@ public class QuartzJobService { @Qualifier(value = ("defaultScheduler")) private Scheduler scheduler; + public void changeQuartzJob(QuartzJobChangeReq req) { + + JobKey jobKey = QuartzKeyGenerator.generateJobKey(req.getJobName(), req.getJobGroup()); + try { + switch (req.getOperationType()) { + case CREATE: { + CreateQuartzJobReq createQuartzJobReq = new CreateQuartzJobReq(); + createQuartzJobReq.setJobKey(jobKey); + createQuartzJobReq.setAllowConcurrent(req.getAllowConcurrent()); + createQuartzJobReq.setMisfireStrategy(req.getMisfireStrategy()); + createQuartzJobReq.setTriggerConfig(req.getTriggerConfig()); + createJob(createQuartzJobReq); + } + case UPDATE: { + // TODO 是否允许修改触发策略?否则无需修改 + resumeJob(jobKey); + break; + } + case RESUME: { + resumeJob(jobKey); + break; + } + case PAUSE: { + pauseJob(jobKey); + break; + } + case TERMINATE: { + deleteJob(jobKey); + break; + } + default: + throw new UnsupportedException(); + } + } catch (Exception e) { + throw new UnexpectedException(""); + } + } + + public void createJob(CreateQuartzJobReq req) throws SchedulerException { createJob(req, null); } + // TODO how can we recognize multi trigger for job. maybe we can use jobName as trigger group. public void createJob(CreateQuartzJobReq req, JobDataMap triggerDataMap) throws SchedulerException { - JobKey jobKey = QuartzKeyGenerator.generateJobKey(req.getScheduleId(), req.getType()); - Class clazz = QuartzJob.class; if (req.getTriggerConfig() != null) { JobDataMap triData = triggerDataMap == null ? new JobDataMap(new HashMap<>(1)) : triggerDataMap; - TriggerKey triggerKey = QuartzKeyGenerator.generateTriggerKey(req.getScheduleId(), req.getType()); + TriggerKey triggerKey = + QuartzKeyGenerator.generateTriggerKey(req.getJobKey().getName(), req.getJobKey().getGroup()); Trigger trigger = buildTrigger(triggerKey, req.getTriggerConfig(), req.getMisfireStrategy(), triData); - JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(jobKey) + JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(req.getJobKey()) .usingJobData(req.getJobDataMap()).build(); scheduler.scheduleJob(jobDetail, trigger); } else { - JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(jobKey) + JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(req.getJobKey()) .usingJobData(req.getJobDataMap()).storeDurably(true).build(); scheduler.addJob(jobDetail, false); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/executor/AbstractQuartzJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/executor/AbstractQuartzJob.java index 947818ad7e..50fcbc1d96 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/executor/AbstractQuartzJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/executor/AbstractQuartzJob.java @@ -30,7 +30,7 @@ import com.oceanbase.odc.service.schedule.job.OnlineSchemaChangeCompleteJob; import com.oceanbase.odc.service.schedule.job.PartitionPlanJob; import com.oceanbase.odc.service.schedule.job.SqlPlanJob; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskType; import lombok.extern.slf4j.Slf4j; @@ -69,8 +69,8 @@ public void run(JobExecutionContext context) { public OdcJob getOdcJob(JobExecutionContext context) { JobKey key = context.getJobDetail().getKey(); - JobType jobType = JobType.valueOf(key.getGroup()); - switch (jobType) { + ScheduleTaskType taskType = ScheduleTaskType.valueOf(key.getGroup()); + switch (taskType) { case SQL_PLAN: return new SqlPlanJob(); case DATA_ARCHIVE: diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleChangeLogService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleChangeLogService.java new file mode 100644 index 0000000000..df03d6f7bb --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleChangeLogService.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.oceanbase.odc.core.shared.constant.ResourceType; +import com.oceanbase.odc.core.shared.exception.NotFoundException; +import com.oceanbase.odc.metadb.schedule.ScheduleChangeLogEntity; +import com.oceanbase.odc.metadb.schedule.ScheduleChangeLogRepository; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeLog; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeLogMapper; + +/** + * @Author:tinker + * @Date: 2024/6/8 15:28 + * @Descripition: + */ + +@Service +public class ScheduleChangeLogService { + @Autowired + private ScheduleChangeLogRepository scheduleChangeLogRepository; + + private static final ScheduleChangeLogMapper mapper = ScheduleChangeLogMapper.INSTANCE; + + public ScheduleChangeLog createChangeLog(ScheduleChangeLog changeLog) { + ScheduleChangeLogEntity entity = mapper.modelToEntity(changeLog); + return mapper.entityToModel(scheduleChangeLogRepository.save(entity)); + } + + public ScheduleChangeLog getByIdAndScheduleId(Long id, Long scheduleId) { + return scheduleChangeLogRepository.findByIdAndScheduleId(id, scheduleId).map(mapper::entityToModel) + .orElseThrow(() -> new NotFoundException( + ResourceType.ODC_SCHEDULE_CHANGE_LOG, "id", id)); + } + + public List listByScheduleId(Long scheduleId) { + return scheduleChangeLogRepository.findByScheduleId(scheduleId).stream().map(mapper::entityToModel).collect( + Collectors.toList()); + } +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java index afda5d7f84..26b2744137 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java @@ -16,14 +16,11 @@ package com.oceanbase.odc.service.schedule; import java.io.File; -import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import javax.validation.constraints.NotNull; @@ -35,74 +32,52 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cglib.beans.BeanMap; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.fasterxml.jackson.core.type.TypeReference; import com.oceanbase.odc.common.json.JsonUtils; -import com.oceanbase.odc.common.util.StringUtils; import com.oceanbase.odc.core.authority.util.SkipAuthorize; import com.oceanbase.odc.core.shared.constant.OrganizationType; -import com.oceanbase.odc.core.shared.constant.ResourceRoleName; import com.oceanbase.odc.core.shared.constant.ResourceType; import com.oceanbase.odc.core.shared.constant.TaskStatus; -import com.oceanbase.odc.core.shared.constant.TaskType; -import com.oceanbase.odc.core.shared.exception.AccessDeniedException; import com.oceanbase.odc.core.shared.exception.NotFoundException; -import com.oceanbase.odc.core.shared.exception.UnexpectedException; import com.oceanbase.odc.core.shared.exception.UnsupportedException; -import com.oceanbase.odc.metadb.collaboration.EnvironmentEntity; import com.oceanbase.odc.metadb.collaboration.EnvironmentRepository; import com.oceanbase.odc.metadb.flow.FlowInstanceRepository; -import com.oceanbase.odc.metadb.flow.ServiceTaskInstanceEntity; -import com.oceanbase.odc.metadb.flow.ServiceTaskInstanceRepository; import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.metadb.schedule.ScheduleRepository; -import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; -import com.oceanbase.odc.metadb.task.TaskEntity; -import com.oceanbase.odc.metadb.task.TaskRepository; import com.oceanbase.odc.service.collaboration.project.ProjectService; -import com.oceanbase.odc.service.common.response.SuccessResponse; import com.oceanbase.odc.service.connection.database.DatabaseService; -import com.oceanbase.odc.service.connection.database.model.Database; -import com.oceanbase.odc.service.dispatch.DispatchResponse; -import com.oceanbase.odc.service.dispatch.RequestDispatcher; -import com.oceanbase.odc.service.dispatch.TaskDispatchChecker; -import com.oceanbase.odc.service.flow.model.FlowNodeStatus; -import com.oceanbase.odc.service.flow.task.model.DatabaseChangeParameters; import com.oceanbase.odc.service.iam.OrganizationService; import com.oceanbase.odc.service.iam.ProjectPermissionValidator; -import com.oceanbase.odc.service.iam.UserService; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; import com.oceanbase.odc.service.iam.model.Organization; -import com.oceanbase.odc.service.iam.model.User; -import com.oceanbase.odc.service.logger.LoggerService; import com.oceanbase.odc.service.objectstorage.ObjectStorageFacade; import com.oceanbase.odc.service.quartz.QuartzJobService; -import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; +import com.oceanbase.odc.service.quartz.model.MisfireStrategy; import com.oceanbase.odc.service.regulation.approval.ApprovalFlowConfigSelector; -import com.oceanbase.odc.service.regulation.risklevel.model.RiskLevel; -import com.oceanbase.odc.service.regulation.risklevel.model.RiskLevelDescriber; import com.oceanbase.odc.service.schedule.factory.ScheduleResponseMapperFactory; import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; -import com.oceanbase.odc.service.schedule.model.DataArchiveClearParameters; -import com.oceanbase.odc.service.schedule.model.DataArchiveRollbackParameters; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.CreateScheduleReq; +import com.oceanbase.odc.service.schedule.model.OperationType; +import com.oceanbase.odc.service.schedule.model.QuartzJobChangeReq; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.QueryScheduleParams; +import com.oceanbase.odc.service.schedule.model.Schedule; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeLog; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; -import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp.ScheduleResponseMapper; +import com.oceanbase.odc.service.schedule.model.ScheduleListResp; +import com.oceanbase.odc.service.schedule.model.ScheduleMapper; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskMapper; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskResp; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskDetailResp; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskListResp; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; -import com.oceanbase.odc.service.schedule.model.TriggerStrategy; -import com.oceanbase.odc.service.task.config.TaskFrameworkEnabledProperties; -import com.oceanbase.odc.service.task.exception.JobException; -import com.oceanbase.odc.service.task.model.ExecutorInfo; +import com.oceanbase.odc.service.schedule.model.UpdateScheduleReq; import com.oceanbase.odc.service.task.model.OdcTaskLogLevel; -import com.oceanbase.odc.service.task.schedule.JobScheduler; import lombok.extern.slf4j.Slf4j; @@ -122,18 +97,9 @@ public class ScheduleService { private AuthenticationFacade authenticationFacade; @Autowired private QuartzJobService quartzJobService; - @Autowired - private UserService userService; - @Autowired - private ObjectStorageFacade objectStorageFacade; - - @Autowired - private LoggerService loggerService; @Autowired - private TaskRepository taskRepository; - @Autowired - private ServiceTaskInstanceRepository serviceTaskRepository; + private ObjectStorageFacade objectStorageFacade; @Autowired private FlowInstanceRepository flowInstanceRepository; @@ -160,33 +126,111 @@ public class ScheduleService { private EnvironmentRepository environmentRepository; @Autowired - private TaskDispatchChecker dispatchChecker; - @Autowired - private RequestDispatcher requestDispatcher; - @Autowired - private TaskFrameworkEnabledProperties taskFrameworkEnabledProperties; + private ScheduleChangeLogService scheduleChangeLogService; @Autowired private OrganizationService organizationService; - @Autowired - private JobScheduler jobScheduler; - private final ScheduleTaskMapper scheduleTaskMapper = ScheduleTaskMapper.INSTANCE; + private final ScheduleMapper scheduleMapper = ScheduleMapper.INSTANCE; - public ScheduleEntity create(ScheduleEntity scheduleConfig) { - return scheduleRepository.save(scheduleConfig); - } @Transactional(rollbackFor = Exception.class) - public void updateJobData(ScheduleEntity scheduleConfig) throws SchedulerException { - JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleConfig.getId(), scheduleConfig.getJobType()); + public void changeSchedule(ScheduleChangeReq req) { + + Schedule targetSchedule; + + // create or load target schedule + if (req.getOperationType() == OperationType.CREATE) { + ScheduleEntity entity = new ScheduleEntity(); + + entity.setProjectId(1L); + entity.setDescription(req.getCreateScheduleReq().getDescription()); + entity.setJobParametersJson(JsonUtils.toJson(req.getCreateScheduleReq().getParameters())); + entity.setTriggerConfigJson(JsonUtils.toJson(req.getCreateScheduleReq().getTriggerConfig())); + entity.setScheduleType(req.getCreateScheduleReq().getType()); + + entity.setMisfireStrategy(MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING); + entity.setStatus(ScheduleStatus.CREATING); + entity.setAllowConcurrent(false); + entity.setOrganizationId(authenticationFacade.currentOrganizationId()); + entity.setCreatorId(authenticationFacade.currentUserId()); + entity.setModifierId(authenticationFacade.currentUserId()); + entity.setDatabaseId(req.getCreateScheduleReq().getDatabaseId()); + entity.setDatabaseName(req.getCreateScheduleReq().getDatabaseName()); + entity.setConnectionId(req.getCreateScheduleReq().getConnectionId()); + + targetSchedule = scheduleMapper.entityToModel(scheduleRepository.save(entity)); + req.setScheduleId(targetSchedule.getId()); + } else { + targetSchedule = nullSafeGetByIdWithCheckPermission(req.getScheduleId(), true); + if (req.getOperationType() == OperationType.UPDATE + && (targetSchedule.getStatus() != ScheduleStatus.PAUSE || hasRunningTask(targetSchedule.getId()))) { + log.warn("Update schedule is not allowed,status={}", targetSchedule.getStatus()); + throw new IllegalStateException("Update schedule is not allowed."); + } + } + + Long approvalFlowInstanceId = createApprovalFlow(); - if (quartzJobService.checkExists(jobKey)) { - quartzJobService.deleteJob(jobKey); + if (approvalFlowInstanceId == null) { + executeChangeSchedule(req); } - quartzJobService.createJob(buildCreateJobReq(scheduleConfig)); - scheduleConfig.setStatus(ScheduleStatus.ENABLED); - scheduleRepository.save(scheduleConfig); + + // create change log for this request + ScheduleChangeLog changeLog = scheduleChangeLogService.createChangeLog( + ScheduleChangeLog.build(targetSchedule.getId(), req.getOperationType(), targetSchedule.getParameters(), + req.getOperationType() == OperationType.UPDATE + ? JsonUtils.toJson(req.getUpdateScheduleReq().getParameters()) + : targetSchedule.getParameters(), + approvalFlowInstanceId)); + log.info("Create change log success,changLog={}", changeLog); + + } + + public void executeChangeSchedule(ScheduleChangeReq req) { + Schedule targetSchedule = nullSafeGetModelById(req.getScheduleId()); + // start to change schedule + switch (req.getOperationType()) { + case CREATE: + case RESUME: { + scheduleRepository.updateStatusById(targetSchedule.getId(), ScheduleStatus.ENABLED); + break; + } + case UPDATE: { + scheduleRepository.updateJobParametersById(req.getScheduleId(), + JsonUtils.toJson(req.getUpdateScheduleReq().getParameters())); + scheduleRepository.updateStatusById(targetSchedule.getId(), ScheduleStatus.ENABLED); + break; + } + case PAUSE: { + scheduleRepository.updateStatusById(targetSchedule.getId(), ScheduleStatus.PAUSE); + break; + } + case TERMINATE: { + scheduleRepository.updateStatusById(targetSchedule.getId(), ScheduleStatus.TERMINATED); + break; + } + default: + throw new UnsupportedException(); + } + + // start change quartzJob + QuartzJobChangeReq quartzJobReq = new QuartzJobChangeReq(); + quartzJobReq.setOperationType(req.getOperationType()); + quartzJobReq.setJobName(targetSchedule.getId().toString()); + quartzJobReq.setJobGroup(targetSchedule.getScheduleType().name()); + quartzJobReq.setTriggerConfig(JsonUtils.fromJson(targetSchedule.getTriggerConfigJson(), TriggerConfig.class)); + quartzJobService.changeQuartzJob(quartzJobReq); + + } + + // return null if approval is not necessary + private Long createApprovalFlow() { + return null; + } + + public ScheduleEntity create(ScheduleEntity scheduleConfig) { + return scheduleRepository.save(scheduleConfig); } public void innerUpdateTriggerData(Long scheduleId, Map triggerDataMap) @@ -231,11 +275,32 @@ public void resume(ScheduleEntity scheduleConfig) throws SchedulerException { @Transactional(rollbackFor = Exception.class) public void terminate(ScheduleEntity scheduleConfig) throws SchedulerException { - JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleConfig.getId(), scheduleConfig.getJobType()); + JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleConfig); quartzJobService.deleteJob(jobKey); - scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.TERMINATION); + scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.TERMINATED); + } + + public void create(CreateScheduleReq req) { + changeSchedule(ScheduleChangeReq.with(req)); + } + + public void pause(Long scheduleId) { + changeSchedule(ScheduleChangeReq.with(scheduleId, OperationType.TERMINATE)); + } + + public void update(Long scheduleId, UpdateScheduleReq req) { + changeSchedule(ScheduleChangeReq.with(scheduleId, req)); } + public void resume(Long scheduleId) { + changeSchedule(ScheduleChangeReq.with(scheduleId, OperationType.TERMINATE)); + } + + public void terminate(Long scheduleId) { + changeSchedule(ScheduleChangeReq.with(scheduleId, OperationType.TERMINATE)); + } + + /** * The method detects whether the database required for scheduled task operation exists. It returns * true and terminates the scheduled task if the database does not exist. If the database exists, it @@ -251,8 +316,8 @@ public boolean terminateIfScheduleInvalid(Long scheduleId) { log.info( "The project or database for scheduled task operation does not exist, and the schedule is being terminated, scheduleId={}", scheduleId); - terminate(scheduleEntityOptional.get()); - } catch (SchedulerException e) { + terminate(scheduleId); + } catch (Exception e) { log.warn("Terminate schedule failed,scheduleId={}", scheduleId); } } @@ -279,201 +344,39 @@ private boolean isInvalidSchedule(ScheduleEntity schedule) { // project not found. return true; } - - try { - Database database = databaseService.getBasicSkipPermissionCheck(schedule.getDatabaseId()); - // database is invalid. - if (!database.getExisted()) { - return true; - } - // database does not belong to any project, or the database and the schedule are not in the same - // project. - if (database.getProject() == null - || !Objects.equals(database.getProject().getId(), schedule.getProjectId())) { - return true; - } - } catch (NotFoundException e) { - // database not found. - return true; - } - // schedule is valid. return false; } - public ScheduleDetailResp triggerJob(Long scheduleId, String jobType) { - ScheduleEntity entity = nullSafeGetByIdWithCheckPermission(scheduleId, true); - if (StringUtils.isEmpty(jobType)) { - jobType = entity.getJobType().name(); - } - try { - quartzJobService.triggerJob(new JobKey(scheduleId.toString(), jobType)); - } catch (Exception e) { - log.warn("Trigger job failed,error={}", e.getMessage()); - throw new RuntimeException("Trigger job failed."); - } - return ScheduleDetailResp.withId(scheduleId); - } - - public ScheduleDetailResp interruptJob(Long scheduleId, Long taskId) { - ScheduleEntity entity = nullSafeGetByIdWithCheckPermission(scheduleId, true); - return interruptJobWithoutPermission(scheduleId, taskId); - } - - public ScheduleDetailResp interruptJobWithoutPermission(Long scheduleId, Long taskId) { - ScheduleTaskEntity taskEntity = scheduleTaskService.nullSafeGetById(taskId); - ExecutorInfo executorInfo = JsonUtils.fromJson(taskEntity.getExecutor(), ExecutorInfo.class); - if (taskFrameworkEnabledProperties.isEnabled() && taskEntity.getJobId() != null) { - try { - jobScheduler.cancelJob(taskEntity.getJobId()); - return ScheduleDetailResp.withId(scheduleId); - } catch (JobException e) { - log.warn("Cancel job failed,jobId={}", taskEntity.getJobId(), e); - throw new UnexpectedException("Cancel job failed!", e); - } - } - // Local interrupt task. - if (dispatchChecker.isThisMachine(executorInfo)) { - JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleId, JobType.valueOf(taskEntity.getJobGroup())); - try { - quartzJobService.interruptJob(jobKey); - log.info("Local interrupt task succeed,taskId={}", taskId); - } catch (Exception e) { - log.warn("Interrupt job failed,error={}", e.getMessage()); - throw new UnexpectedException("Interrupt job failed,please try again."); - } - return ScheduleDetailResp.withId(scheduleId); - } - // Remote interrupt task. - try { - DispatchResponse response = - requestDispatcher.forward(executorInfo.getHost(), executorInfo.getPort()); - log.info("Remote interrupt task succeed,taskId={}", taskId); - return response.getContentByType( - new TypeReference>() {}).getData(); - } catch (Exception e) { - log.warn("Remote interrupt task failed, taskId={}", taskId, e); - throw new UnexpectedException(String.format("Remote interrupt task failed, taskId=%s", taskId)); - } + public void stopTask(Long scheduleId, Long scheduleTaskId) { + nullSafeGetByIdWithCheckPermission(scheduleId, true); + scheduleTaskService.stop(scheduleTaskId); } /** * @param scheduleId the task must belong to a valid schedule,so this param is not be null. - * @param taskId the task uid. Start a paused or pending task. + * @param scheduleTaskId the task uid. Start a paused or pending task. */ - public ScheduleTaskResp startTask(Long scheduleId, Long taskId) { - ScheduleEntity scheduleEntity = nullSafeGetByIdWithCheckPermission(scheduleId, true); - return startTaskWithoutPermission(scheduleId, taskId); - } - - public ScheduleTaskResp startTaskWithoutPermission(Long scheduleId, Long taskId) { - ScheduleTaskEntity taskEntity = scheduleTaskService.nullSafeGetById(taskId); - JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleId, JobType.valueOf(taskEntity.getJobGroup())); - if (!taskEntity.getStatus().isRetryAllowed()) { - log.warn( - "The task cannot be restarted because it is currently in progress or has already completed.JobKey={}", - jobKey); - throw new IllegalStateException( - "The task cannot be restarted because it is currently in progress or has already completed."); - } - try { - // create a single trigger job if job not found. - if (!quartzJobService.checkExists(jobKey)) { - log.info("Job not found and will be recreated,jobKey={},taskId={}", jobKey, taskId); - CreateQuartzJobReq req = new CreateQuartzJobReq(); - req.setScheduleId(scheduleId); - req.setType(JobType.valueOf(taskEntity.getJobGroup())); - TriggerConfig triggerConfig = new TriggerConfig(); - triggerConfig.setTriggerStrategy(TriggerStrategy.START_NOW); - req.setTriggerConfig(triggerConfig); - quartzJobService.createJob(req, ScheduleTaskUtils.buildTriggerDataMap(taskId)); - log.info("Job recreated,jobKey={}", jobKey); - return ScheduleTaskResp.withId(taskId); - } else { - return scheduleTaskService.start(taskId); - } - } catch (SchedulerException e) { - log.warn("Unexpected exception while check job!", e); - throw new IllegalStateException("Unexpected exception while check job!"); - } + public void startTask(Long scheduleId, Long scheduleTaskId) { + nullSafeGetByIdWithCheckPermission(scheduleId, true); + scheduleTaskService.start(scheduleTaskId); } - public ScheduleTaskResp dataArchiveDelete(Long scheduleId, Long taskId) { + public void dataArchiveDelete(Long scheduleId, Long taskId) { ScheduleEntity scheduleEntity = nullSafeGetById(scheduleId); - if (scheduleEntity.getJobType() != JobType.DATA_ARCHIVE) { + if (scheduleEntity.getScheduleType() != ScheduleType.DATA_ARCHIVE) { throw new UnsupportedException(); } - JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleId, JobType.DATA_ARCHIVE_DELETE); - - ScheduleTaskEntity taskEntity = scheduleTaskService.nullSafeGetById(taskId); - if (taskEntity.getStatus() != TaskStatus.DONE) { - log.warn("Delete is not allowed because the data archive job has not succeeded.JobKey={}", jobKey); - throw new IllegalStateException("Delete is not allowed because the data archive job has not succeeded."); - } - try { - if (quartzJobService.checkExists(jobKey)) { - log.info("Data archive delete job exists and start delete job,jobKey={}", jobKey); - quartzJobService.deleteJob(jobKey); - } - CreateQuartzJobReq req = new CreateQuartzJobReq(); - req.setScheduleId(scheduleId); - req.setType(JobType.DATA_ARCHIVE_DELETE); - DataArchiveClearParameters parameters = new DataArchiveClearParameters(); - parameters.setDataArchiveTaskId(taskId); - TriggerConfig triggerConfig = new TriggerConfig(); - triggerConfig.setTriggerStrategy(TriggerStrategy.START_NOW); - req.getJobDataMap().putAll(BeanMap.create(parameters)); - req.setTriggerConfig(triggerConfig); - quartzJobService.createJob(req); - } catch (SchedulerException e) { - throw new RuntimeException(e); - } - ScheduleTaskResp scheduleTaskResp = ScheduleTaskResp.withId(taskId); - scheduleTaskResp.setJobName(jobKey.getName()); - scheduleTaskResp.setJobGroup(jobKey.getGroup()); - return scheduleTaskResp; } - public ScheduleTaskResp rollbackTask(Long scheduleId, Long taskId) { - ScheduleEntity scheduleEntity = nullSafeGetByIdWithCheckPermission(scheduleId, true); - if (scheduleEntity.getJobType() != JobType.DATA_ARCHIVE) { + public void rollbackTask(Long scheduleId, Long scheduleTaskId) { + Schedule schedule = nullSafeGetByIdWithCheckPermission(scheduleId, true); + if (schedule.getScheduleType() != ScheduleType.DATA_ARCHIVE) { throw new UnsupportedException(); } - - JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleId, JobType.DATA_ARCHIVE_ROLLBACK); - ScheduleTaskEntity taskEntity = scheduleTaskService.nullSafeGetById(taskId); - if (!taskEntity.getStatus().isTerminated()) { - log.warn("Rollback is not allowed because the data archive job is running.JobKey={}", jobKey); - throw new IllegalStateException("Rollback is not allowed because the data archive job is running."); - } - - try { - if (quartzJobService.checkExists(jobKey)) { - log.info("Data archive rollback job exists and start delete job,jobKey={}", jobKey); - quartzJobService.deleteJob(jobKey); - } - CreateQuartzJobReq req = new CreateQuartzJobReq(); - req.setScheduleId(scheduleId); - req.setType(JobType.DATA_ARCHIVE_ROLLBACK); - DataArchiveRollbackParameters parameters = new DataArchiveRollbackParameters(); - parameters.setDataArchiveTaskId(taskId); - req.getJobDataMap().putAll(BeanMap.create(parameters)); - TriggerConfig triggerConfig = new TriggerConfig(); - triggerConfig.setTriggerStrategy(TriggerStrategy.START_NOW); - req.setTriggerConfig(triggerConfig); - quartzJobService.createJob(req); - } catch (SchedulerException e) { - throw new RuntimeException(e); - } - return ScheduleTaskResp.withId(taskId); - } - - public Page listTask(Pageable pageable, Long scheduleId) { - ScheduleEntity entity = nullSafeGetByIdWithCheckPermission(scheduleId); - Page scheduleTaskEntities = scheduleTaskService.listTask(pageable, entity.getId()); - return scheduleTaskEntities.map(scheduleTaskMapper::entityToModel); + scheduleTaskService.rollbackTask(scheduleTaskId); } public void updateStatusById(Long id, ScheduleStatus status) { @@ -482,7 +385,7 @@ public void updateStatusById(Long id, ScheduleStatus status) { public void refreshScheduleStatus(Long scheduleId) { ScheduleEntity scheduleEntity = nullSafeGetById(scheduleId); - JobKey key = QuartzKeyGenerator.generateJobKey(scheduleEntity.getId(), scheduleEntity.getJobType()); + JobKey key = QuartzKeyGenerator.generateJobKey(scheduleEntity); ScheduleStatus status = scheduleEntity.getStatus(); if (status == ScheduleStatus.PAUSE) { return; @@ -518,7 +421,7 @@ public void refreshScheduleStatus(Long scheduleId) { public void updateStatusByFlowInstanceId(Long id, ScheduleStatus status) { Long scheduleId = flowInstanceRepository.findScheduleIdByFlowInstanceId(id); if (scheduleId != null) { - ScheduleEntity schedule = nullSafeGetById(scheduleId); + Schedule schedule = nullSafeGetModelById(scheduleId); if (schedule.getStatus() == ScheduleStatus.APPROVING) { updateStatusById(scheduleId, status); } @@ -529,27 +432,19 @@ public void updateJobParametersById(Long id, String jobParameters) { scheduleRepository.updateJobParametersById(id, jobParameters); } - public ScheduleDetailResp getById(Long id) { - ScheduleEntity entity = nullSafeGetByIdWithCheckPermission(id); - ScheduleResponseMapper mapper = scheduleResponseMapperFactory.generate(entity); - return mapper.map(entity); + + public ScheduleTaskDetailResp detailScheduleTask(Long scheduleId, Long scheduleTaskId) { + Schedule schedule = nullSafeGetByIdWithCheckPermission(scheduleId); + return scheduleTaskService.getScheduleTaskDetailResp(scheduleTaskId, schedule.getId()); } - public ScheduleTaskResp detailScheduleTask(Long scheduleId, Long scheduleTaskId) { - ScheduleEntity scheduleEntity = nullSafeGetByIdWithCheckPermission(scheduleId); - ScheduleTaskResp detail = scheduleTaskService.detail(scheduleTaskId); - // Throw a NotFoundException if the schedule task does not belong to the schedule. - if (!detail.getJobName().equals(scheduleEntity.getId().toString())) { - throw new NotFoundException(ResourceType.ODC_SCHEDULE_TASK, "scheduleTaskId", scheduleTaskId); - } - return detail; + public ScheduleDetailResp detailSchedule(Long scheduleId) { + Schedule schedule = nullSafeGetByIdWithCheckPermission(scheduleId); + return scheduleResponseMapperFactory.generateScheduleDetailResp(schedule); } - public Page list(@NotNull Pageable pageable, @NotNull QueryScheduleParams params) { - if (StringUtils.isNotBlank(params.getCreator())) { - params.setCreatorIds(userService.getUsersByFuzzyNameWithoutPermissionCheck( - params.getCreator()).stream().map(User::getId).collect(Collectors.toSet())); - } + public Page getScheduleListResp(@NotNull Pageable pageable, @NotNull QueryScheduleParams params) { + if (authenticationFacade.currentOrganization().getType() == OrganizationType.TEAM) { Set projectIds = params.getProjectId() == null ? projectService.getMemberProjectIds(authenticationFacade.currentUserId()) @@ -559,18 +454,26 @@ public Page list(@NotNull Pageable pageable, @NotNull QueryS } params.setProjectIds(projectIds); } + params.setOrganizationId(authenticationFacade.currentOrganizationId()); Page returnValue = scheduleRepository.find(pageable, params); + List res = scheduleResponseMapperFactory.generateListResponse(returnValue.getContent()); + return returnValue.isEmpty() ? Page.empty() - : returnValue.map(scheduleResponseMapperFactory.generate(returnValue.getContent())::map); + : new PageImpl<>(res, returnValue.getPageable(), returnValue.getTotalPages()); + } + + public Page listScheduleTask(@NotNull Pageable pageable, @NotNull Long scheduleId) { + nullSafeGetByIdWithCheckPermission(scheduleId, false); + return scheduleTaskService.getScheduleTaskListResp(pageable, scheduleId); } public List getAsyncDownloadUrl(Long id, List objectIds) { - ScheduleEntity scheduleEntity = nullSafeGetByIdWithCheckPermission(id); + Schedule schedule = nullSafeGetByIdWithCheckPermission(id); List downloadUrls = Lists.newArrayList(); for (String objectId : objectIds) { downloadUrls.add(objectStorageFacade.getDownloadUrl( - "async".concat(File.separator).concat(scheduleEntity.getCreatorId().toString()), + "async".concat(File.separator).concat(schedule.getCreatorId().toString()), objectId)); } return downloadUrls; @@ -578,80 +481,37 @@ public List getAsyncDownloadUrl(Long id, List objectIds) { public String getLog(Long scheduleId, Long taskId, OdcTaskLogLevel logLevel) { nullSafeGetByIdWithCheckPermission(scheduleId); - return getLogWithoutPermission(scheduleId, taskId, logLevel); - } - - public String getLogWithoutPermission(Long scheduleId, Long taskId, OdcTaskLogLevel logLevel) { - ScheduleTaskEntity taskEntity = scheduleTaskService.nullSafeGetById(taskId); - if (taskFrameworkEnabledProperties.isEnabled() && taskEntity.getJobId() != null) { - try { - return loggerService.getLogByTaskFramework(logLevel, taskEntity.getJobId()); - } catch (IOException e) { - log.warn("Copy input stream to file failed.", e); - throw new UnexpectedException("Copy input stream to file failed."); - } - } - ExecutorInfo executorInfo = JsonUtils.fromJson(taskEntity.getExecutor(), ExecutorInfo.class); - if (!dispatchChecker.isThisMachine(executorInfo)) { - try { - DispatchResponse response = - requestDispatcher.forward(executorInfo.getHost(), executorInfo.getPort()); - log.info("Remote get task log succeed,taskId={}", taskId); - return response.getContentByType( - new TypeReference>() {}).getData(); - } catch (Exception e) { - log.warn("Remote get task log failed, taskId={}", taskId, e); - throw new UnexpectedException(String.format("Remote interrupt task failed, taskId=%s", taskId)); - } - } return scheduleTaskService.getScheduleTaskLog(taskId, logLevel); } - public boolean hasExecutingAsyncTask(ScheduleEntity schedule) { - Set executingTaskIds = serviceTaskRepository.findByScheduleIdAndTaskTypeAndStatusIn(schedule.getId(), - TaskType.ASYNC, FlowNodeStatus.getNotFinalStatuses()).stream().map( - ServiceTaskInstanceEntity::getTargetTaskId) - .collect(Collectors.toSet()); - List taskEntities = taskRepository.findByIdIn(executingTaskIds); - for (TaskEntity taskEntity : taskEntities) { - Long timeoutMillis = JsonUtils.fromJson(taskEntity.getParametersJson(), DatabaseChangeParameters.class) - .getTimeoutMillis(); - if (taskEntity.getCreateTime().getTime() + timeoutMillis > System.currentTimeMillis()) { - return true; - } - } - return false; - } - - public boolean hasExecutingScheduleTask(Long scheduleId) { - return !scheduleTaskService.listTaskByJobNameAndStatus( - scheduleId.toString(), TaskStatus.getProcessingStatus()).isEmpty(); - } - - public ScheduleEntity nullSafeGetByIdWithCheckPermission(Long id) { + public Schedule nullSafeGetByIdWithCheckPermission(Long id) { return nullSafeGetByIdWithCheckPermission(id, false); } - public ScheduleEntity nullSafeGetByIdWithCheckPermission(Long id, boolean isWrite) { - ScheduleEntity scheduleEntity = nullSafeGetById(id); - Long projectId = scheduleEntity.getProjectId(); - if (isWrite) { - List resourceRoleNames = getApproverRoleNames(scheduleEntity); - if (resourceRoleNames.isEmpty()) { - resourceRoleNames = ResourceRoleName.all(); - } - if ((Objects.nonNull(projectId) - && !projectPermissionValidator.hasProjectRole(projectId, resourceRoleNames))) { - throw new AccessDeniedException(); - } - } else { - - if (Objects.nonNull(projectId) - && !projectPermissionValidator.hasProjectRole(projectId, ResourceRoleName.all())) { - throw new AccessDeniedException(); - } - } - return scheduleEntity; + public Schedule nullSafeGetByIdWithCheckPermission(Long id, boolean isWrite) { + Schedule schedule = nullSafeGetModelById(id); + // Long projectId = schedule.getProjectId(); + // if (isWrite) { + // List resourceRoleNames = getApproverRoleNames(Schedule); + // if (resourceRoleNames.isEmpty()) { + // resourceRoleNames = ResourceRoleName.all(); + // } + // if ((Objects.nonNull(projectId) + // && !projectPermissionValidator.hasProjectRole(projectId, resourceRoleNames))) { + // throw new AccessDeniedException(); + // } + // } else { + // + // if (Objects.nonNull(projectId) + // && !projectPermissionValidator.hasProjectRole(projectId, ResourceRoleName.all())) { + // throw new AccessDeniedException(); + // } + // } + return schedule; + } + + public Schedule nullSafeGetModelById(Long id) { + return scheduleMapper.entityToModel(nullSafeGetById(id)); } public ScheduleEntity nullSafeGetById(Long id) { @@ -668,17 +528,11 @@ private Trigger nullSafeGetScheduleTrigger(ScheduleEntity schedule) throws Sched return trigger; } - private Trigger getScheduleTrigger(ScheduleEntity schedule) throws SchedulerException { - return quartzJobService.getTrigger( - QuartzKeyGenerator.generateTriggerKey(schedule.getId(), schedule.getJobType())); - } - private CreateQuartzJobReq buildCreateJobReq(ScheduleEntity schedule) { CreateQuartzJobReq createQuartzJobReq = new CreateQuartzJobReq(); - createQuartzJobReq.setScheduleId(schedule.getId()); - createQuartzJobReq.setType(schedule.getJobType()); + createQuartzJobReq.setJobKey(QuartzKeyGenerator.generateJobKey(schedule)); createQuartzJobReq.setTriggerConfig(JsonUtils.fromJson(schedule.getTriggerConfigJson(), TriggerConfig.class)); - if (schedule.getJobType() == JobType.ONLINE_SCHEMA_CHANGE_COMPLETE) { + if (schedule.getScheduleType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE) { createQuartzJobReq.getJobDataMap().putAll(JsonUtils.fromJson(schedule.getJobParametersJson(), Map.class)); } else { createQuartzJobReq.getJobDataMap().putAll(BeanMap.create(schedule)); @@ -692,20 +546,22 @@ private CreateQuartzJobReq buildCreateJobReq(ScheduleEntity schedule) { return createQuartzJobReq; } - private List getApproverRoleNames(ScheduleEntity entity) { - Database database = databaseService.detail(entity.getDatabaseId()); - EnvironmentEntity environment = environmentRepository.findById(database.getEnvironment().getId()).orElse(null); - RiskLevelDescriber riskLevelDescriber = new RiskLevelDescriber(); - riskLevelDescriber.setDatabaseName(database.getName()); - riskLevelDescriber.setProjectName(database.getProject().getName()); - riskLevelDescriber.setEnvironmentId(database.getEnvironment().getId().toString()); - riskLevelDescriber.setEnvironmentName(environment == null ? null : environment.getName()); - riskLevelDescriber.setTaskType(TaskType.ALTER_SCHEDULE.name()); - RiskLevel riskLevel = approvalFlowConfigSelector.select(riskLevelDescriber); - return riskLevel.getApprovalFlowConfig().getNodes().stream().filter(node -> node.getResourceRoleName() != null) - .map( - node -> ResourceRoleName.valueOf(node.getResourceRoleName())) - .collect(Collectors.toList()); + private Trigger getScheduleTrigger(ScheduleEntity schedule) throws SchedulerException { + return quartzJobService.getTrigger(QuartzKeyGenerator.generateTriggerKey(schedule)); + } + + public ScheduleChangeLog getChangeLog(Long id, Long scheduleChangeLogId) { + Schedule schedule = nullSafeGetByIdWithCheckPermission(id, false); + return scheduleChangeLogService.getByIdAndScheduleId(scheduleChangeLogId, schedule.getId()); + } + + public List listScheduleChangeLog(Long id) { + Schedule schedule = nullSafeGetByIdWithCheckPermission(id, false); + return scheduleChangeLogService.listByScheduleId(schedule.getId()); + } + + public boolean hasRunningTask(Long id) { + return false; } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java index 1be8110dcd..89cd7b4867 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java @@ -16,21 +16,26 @@ package com.oceanbase.odc.service.schedule; import java.io.File; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.apache.commons.io.input.ReversedLinesFileReader; import org.quartz.JobKey; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cglib.beans.BeanMap; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.core.type.TypeReference; +import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.core.authority.util.SkipAuthorize; import com.oceanbase.odc.core.shared.constant.ErrorCodes; import com.oceanbase.odc.core.shared.constant.ResourceType; @@ -38,16 +43,35 @@ import com.oceanbase.odc.core.shared.exception.InternalServerError; import com.oceanbase.odc.core.shared.exception.NotFoundException; import com.oceanbase.odc.core.shared.exception.UnexpectedException; +import com.oceanbase.odc.core.shared.exception.UnsupportedException; import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.metadb.schedule.ScheduleTaskRepository; import com.oceanbase.odc.metadb.schedule.ScheduleTaskSpecs; +import com.oceanbase.odc.service.common.response.SuccessResponse; +import com.oceanbase.odc.service.dispatch.DispatchResponse; +import com.oceanbase.odc.service.dispatch.RequestDispatcher; +import com.oceanbase.odc.service.dispatch.TaskDispatchChecker; import com.oceanbase.odc.service.dlm.DLMService; +import com.oceanbase.odc.service.logger.LoggerService; import com.oceanbase.odc.service.quartz.QuartzJobService; import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; +import com.oceanbase.odc.service.schedule.model.DataArchiveClearParameters; +import com.oceanbase.odc.service.schedule.model.DataArchiveRollbackParameters; +import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; +import com.oceanbase.odc.service.schedule.model.ScheduleTask; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskDetailResp; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskListResp; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskListRespMapper; import com.oceanbase.odc.service.schedule.model.ScheduleTaskMapper; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskResp; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskType; +import com.oceanbase.odc.service.schedule.model.TriggerConfig; +import com.oceanbase.odc.service.schedule.model.TriggerStrategy; +import com.oceanbase.odc.service.task.config.TaskFrameworkEnabledProperties; +import com.oceanbase.odc.service.task.exception.JobException; +import com.oceanbase.odc.service.task.model.ExecutorInfo; import com.oceanbase.odc.service.task.model.OdcTaskLogLevel; +import com.oceanbase.odc.service.task.schedule.JobScheduler; import lombok.extern.slf4j.Slf4j; @@ -71,6 +95,22 @@ public class ScheduleTaskService { @Autowired private DLMService dlmService; + @Autowired + private TaskFrameworkEnabledProperties taskFrameworkEnabledProperties; + + @Autowired + private JobScheduler jobScheduler; + + @Autowired + private TaskDispatchChecker dispatchChecker; + + @Autowired + private RequestDispatcher requestDispatcher; + + @Autowired + private LoggerService loggerService; + + private final ScheduleTaskMapper scheduleTaskMapper = ScheduleTaskMapper.INSTANCE; @Value("${odc.log.directory:./log}") @@ -78,20 +118,26 @@ public class ScheduleTaskService { private static final String LOG_PATH_PATTERN = "%s/scheduleTask/%s-%s/%s/log.%s"; - public ScheduleTaskResp detail(Long id) { - ScheduleTaskEntity entity = nullSafeGetById(id); - ScheduleTaskResp scheduleTaskResp = scheduleTaskMapper.entityToModel(entity); - switch (JobType.valueOf(entity.getJobGroup())) { + public ScheduleTaskDetailResp getScheduleTaskDetailResp(Long id, Long scheduleId) { + ScheduleTask scheduleTask = nullSafeGetByIdAndScheduleId(id, scheduleId); + ScheduleTaskDetailResp res = new ScheduleTaskDetailResp(); + res.setId(scheduleTask.getId()); + res.setType(ScheduleTaskType.valueOf(scheduleTask.getJobGroup())); + res.setStatus(scheduleTask.getStatus()); + res.setFireTime(scheduleTask.getFireTime()); + res.setCreateTime(scheduleTask.getCreateTime()); + res.setUpdateTime(scheduleTask.getUpdateTime()); + switch (res.getType()) { case DATA_ARCHIVE: case DATA_ARCHIVE_ROLLBACK: case DATA_ARCHIVE_DELETE: case DATA_DELETE: { - scheduleTaskResp.setExecutionDetails(dlmService.getExecutionDetailByScheduleTaskId(id)); + res.setExecutionDetails(dlmService.getExecutionDetailByScheduleTaskId(scheduleTask.getId())); } default: break; } - return scheduleTaskResp; + return res; } public ScheduleTaskEntity create(ScheduleTaskEntity taskEntity) { @@ -101,27 +147,84 @@ public ScheduleTaskEntity create(ScheduleTaskEntity taskEntity) { /** * Trigger an existing task to retry or resume a terminated task. */ - public ScheduleTaskResp start(Long taskId) { - ScheduleTaskEntity taskEntity = nullSafeGetById(taskId); - if (taskEntity.getStatus() == TaskStatus.RUNNING || taskEntity.getStatus() == TaskStatus.DONE) { - throw new IllegalStateException(); + public void start(Long id) { + ScheduleTask scheduleTask = nullSafeGetModelById(id); + if (!scheduleTask.getStatus().isRetryAllowed()) { + log.warn( + "The task cannot be restarted because it is currently in progress or has already completed,scheduleTaskId={}", + id); + throw new IllegalStateException( + "The task cannot be restarted because it is currently in progress or has already completed."); } try { - quartzJobService.triggerJob(new JobKey(taskEntity.getJobName(), taskEntity.getJobGroup()), - ScheduleTaskUtils.buildTriggerDataMap(taskId)); + quartzJobService.triggerJob(new JobKey(scheduleTask.getJobName(), scheduleTask.getJobGroup()), + ScheduleTaskUtils.buildTriggerDataMap(id)); } catch (SchedulerException e) { - log.warn("Start task failed,taskId={}", taskId); + log.warn("Trigger schedule task failed,scheduleTaskId={}", id); throw new InternalServerError(e.getMessage()); } - return ScheduleTaskResp.withId(taskId); + } + + public void stop(Long id) { + ScheduleTask scheduleTask = nullSafeGetModelById(id); + ExecutorInfo executorInfo = JsonUtils.fromJson(scheduleTask.getExecutor(), ExecutorInfo.class); + if (taskFrameworkEnabledProperties.isEnabled() && scheduleTask.getJobId() != null) { + try { + jobScheduler.cancelJob(scheduleTask.getJobId()); + return; + } catch (JobException e) { + log.warn("Cancel job failed,jobId={}", scheduleTask.getJobId(), e); + throw new UnexpectedException("Cancel job failed!", e); + } + } + // Local interrupt task. + if (dispatchChecker.isThisMachine(executorInfo)) { + JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleTask.getJobName(), scheduleTask.getJobGroup()); + try { + quartzJobService.interruptJob(jobKey); + log.info("Local interrupt task succeed,taskId={}", id); + } catch (Exception e) { + log.warn("Interrupt job failed,error={}", e.getMessage()); + throw new UnexpectedException("Interrupt job failed,please try again."); + } + } + // Remote interrupt task. + try { + DispatchResponse response = + requestDispatcher.forward(executorInfo.getHost(), executorInfo.getPort()); + log.info("Remote interrupt task succeed,taskId={}", id); + } catch (Exception e) { + log.warn("Remote interrupt task failed, taskId={}", id, e); + throw new UnexpectedException(String.format("Remote interrupt task failed, taskId=%s", id)); + } + } + + + + public void updateStatusById(Long id, TaskStatus status) { + scheduleTaskRepository.updateStatusById(id, status); + } + + public void update(ScheduleTask scheduleTask) { + ScheduleTaskEntity entity = scheduleTaskMapper.modelToEntity(scheduleTask); + scheduleTaskRepository.update(entity); + } + + public int updateParameters(Long id, String parameters) { + return scheduleTaskRepository.updateTaskParameters(id, parameters); } - public Page listTask(Pageable pageable, Long scheduleId) { + public Page list(Pageable pageable, Long scheduleId) { Specification specification = Specification.where(ScheduleTaskSpecs.jobNameEquals(scheduleId.toString())); - return scheduleTaskRepository.findAll(specification, pageable); + return scheduleTaskRepository.findAll(specification, pageable).map(scheduleTaskMapper::entityToModel); + } + + public Page getScheduleTaskListResp(Pageable pageable, Long scheduleId) { + return list(pageable, scheduleId).map(ScheduleTaskListRespMapper::map); + } public List listTaskByJobNameAndStatus(String jobName, List statuses) { @@ -129,29 +232,63 @@ public List listTaskByJobNameAndStatus(String jobName, List< } - public Optional findByJobId(Long jobId) { + public Optional findByJobId(Long jobId) { List scheduleTasks = scheduleTaskRepository.findByJobId(jobId); if (scheduleTasks != null) { if (scheduleTasks.size() > 1) { throw new IllegalStateException("Query scheduleTask by jobId occur error, except 1 but found " + scheduleTasks.size() + ",jobId=" + jobId); } else if (scheduleTasks.size() == 1) { - return Optional.of(scheduleTasks.get(0)); + return Optional.of(scheduleTaskMapper.entityToModel(scheduleTasks.get(0))); } } return Optional.empty(); } + public ScheduleTask nullSafeGetModelById(Long id) { + return scheduleTaskMapper.entityToModel(nullSafeGetById(id)); + } + public ScheduleTaskEntity nullSafeGetById(Long id) { Optional scheduleEntityOptional = scheduleTaskRepository.findById(id); return scheduleEntityOptional .orElseThrow(() -> new NotFoundException(ResourceType.ODC_SCHEDULE_TASK, "id", id)); } + public ScheduleTask nullSafeGetByIdAndScheduleId(Long id, Long scheduleId) { + Optional scheduleEntityOptional = scheduleTaskRepository.findByIdAndJobName(id, scheduleId); + return scheduleTaskMapper.entityToModel(scheduleEntityOptional + .orElseThrow(() -> new NotFoundException(ResourceType.ODC_SCHEDULE_TASK, "id", id))); + } + public String getScheduleTaskLog(Long id, OdcTaskLogLevel logLevel) { - ScheduleTaskEntity taskEntity = nullSafeGetById(id); + ScheduleTask scheduleTask = nullSafeGetModelById(id); + + if (taskFrameworkEnabledProperties.isEnabled() && scheduleTask.getJobId() != null) { + try { + return loggerService.getLogByTaskFramework(logLevel, scheduleTask.getJobId()); + } catch (IOException e) { + log.warn("Copy input stream to file failed.", e); + throw new UnexpectedException("Copy input stream to file failed."); + } + } + ExecutorInfo executorInfo = JsonUtils.fromJson(scheduleTask.getExecutor(), ExecutorInfo.class); + if (!dispatchChecker.isThisMachine(executorInfo)) { + try { + DispatchResponse response = + requestDispatcher.forward(executorInfo.getHost(), executorInfo.getPort()); + log.info("Remote get task log succeed,taskId={}", id); + return response.getContentByType( + new TypeReference>() {}).getData(); + } catch (Exception e) { + log.warn("Remote get task log failed, taskId={}", id, e); + throw new UnexpectedException(String.format("Remote interrupt task failed, taskId=%s", id)); + } + } + + String filePath = String.format(LOG_PATH_PATTERN, logDirectory, - taskEntity.getJobName(), taskEntity.getJobGroup(), taskEntity.getId(), + scheduleTask.getJobName(), scheduleTask.getJobGroup(), id, logLevel.name().toLowerCase()); File logFile = new File(filePath); if (!logFile.exists()) { @@ -181,4 +318,91 @@ public String getScheduleTaskLog(Long id, OdcTaskLogLevel logLevel) { throw new UnexpectedException("Read task log file failed, details: " + ex.getMessage(), ex); } } + + public void correctScheduleTaskStatus(Long scheduleId) { + List toBeCorrectedList = listTaskByJobNameAndStatus( + scheduleId.toString(), TaskStatus.getProcessingStatus()); + // For the scenario where the task framework is switched from closed to open, it is necessary to + // correct + // the status of tasks that were not completed while in the closed state. + if (taskFrameworkEnabledProperties.isEnabled()) { + toBeCorrectedList = + toBeCorrectedList.stream().filter(o -> o.getJobId() == null).collect(Collectors.toList()); + } + toBeCorrectedList.forEach(task -> { + updateStatusById(task.getId(), TaskStatus.CANCELED); + log.info("Task status correction successful,scheduleTaskId={}", task.getId()); + }); + } + + + @SkipAuthorize("odc internal usage") + public void triggerDataArchiveDelete(Long scheduleTaskId) { + + ScheduleTask dataArchiveTask = nullSafeGetModelById(scheduleTaskId); + + + JobKey jobKey = QuartzKeyGenerator.generateJobKey(dataArchiveTask.getJobName(), + ScheduleTaskType.DATA_ARCHIVE_DELETE.name()); + + if (dataArchiveTask.getStatus() != TaskStatus.DONE) { + log.warn("Delete is not allowed because the data archive job has not succeeded.JobKey={}", jobKey); + throw new IllegalStateException("Delete is not allowed because the data archive job has not succeeded."); + } + + try { + if (quartzJobService.checkExists(jobKey)) { + log.info("Data archive delete job exists and start delete job,jobKey={}", jobKey); + quartzJobService.deleteJob(jobKey); + } + CreateQuartzJobReq req = new CreateQuartzJobReq(); + req.setJobKey(jobKey); + DataArchiveClearParameters parameters = new DataArchiveClearParameters(); + parameters.setDataArchiveTaskId(scheduleTaskId); + TriggerConfig triggerConfig = new TriggerConfig(); + triggerConfig.setTriggerStrategy(TriggerStrategy.START_NOW); + req.getJobDataMap().putAll(BeanMap.create(parameters)); + req.setTriggerConfig(triggerConfig); + quartzJobService.createJob(req); + } catch (SchedulerException e) { + throw new RuntimeException(e); + } + } + + + public void rollbackTask(Long scheduleTaskId) { + ScheduleTask scheduleTask = nullSafeGetModelById(scheduleTaskId); + if (ScheduleTaskType.DATA_ARCHIVE_DELETE.name().equals(scheduleTask.getJobGroup())) { + log.warn("Rollback is not allowed for taskType={}", scheduleTask.getJobGroup()); + throw new UnsupportedException("Rollback is not allowed."); + } + JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleTask.getJobName(), + ScheduleTaskType.DATA_ARCHIVE_ROLLBACK.name()); + if (!scheduleTask.getStatus().isTerminated()) { + log.warn("Rollback is not allowed because the data archive job is running.JobKey={}", jobKey); + throw new IllegalStateException("Rollback is not allowed because the data archive job is running."); + } + + + try { + if (quartzJobService.checkExists(jobKey)) { + log.info("Data archive rollback job exists and start delete job,jobKey={}", jobKey); + quartzJobService.deleteJob(jobKey); + } + CreateQuartzJobReq req = new CreateQuartzJobReq(); + req.setJobKey(jobKey); + DataArchiveRollbackParameters parameters = new DataArchiveRollbackParameters(); + parameters.setDataArchiveTaskId(scheduleTaskId); + req.getJobDataMap().putAll(BeanMap.create(parameters)); + TriggerConfig triggerConfig = new TriggerConfig(); + triggerConfig.setTriggerStrategy(TriggerStrategy.START_NOW); + req.setTriggerConfig(triggerConfig); + quartzJobService.createJob(req); + } catch (SchedulerException e) { + throw new UnsupportedException(e.getMessage()); + } + } + + + } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java index a33e6a2ff8..287b4b0d55 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java @@ -17,30 +17,40 @@ import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.oceanbase.odc.core.shared.constant.FlowStatus; -import com.oceanbase.odc.core.shared.constant.TaskType; -import com.oceanbase.odc.metadb.flow.FlowInstanceEntity; -import com.oceanbase.odc.metadb.flow.FlowInstanceRepository; -import com.oceanbase.odc.metadb.flow.UserTaskInstanceEntity; -import com.oceanbase.odc.metadb.iam.UserEntity; +import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.metadb.iam.UserRepository; +import com.oceanbase.odc.metadb.schedule.LatestScheduleTaskLinkEntity; +import com.oceanbase.odc.metadb.schedule.LatestScheduleTaskLinkRepository; import com.oceanbase.odc.metadb.schedule.ScheduleEntity; +import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; +import com.oceanbase.odc.metadb.schedule.ScheduleTaskRepository; +import com.oceanbase.odc.service.common.model.InnerUser; +import com.oceanbase.odc.service.connection.ConnectionService; import com.oceanbase.odc.service.connection.database.DatabaseService; import com.oceanbase.odc.service.connection.database.model.Database; -import com.oceanbase.odc.service.dlm.DlmLimiterService; -import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; -import com.oceanbase.odc.service.flow.ApprovalPermissionService; -import com.oceanbase.odc.service.flow.model.FlowNodeStatus; -import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp.ScheduleResponseMapper; +import com.oceanbase.odc.service.connection.model.ConnectionConfig; +import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; +import com.oceanbase.odc.service.dlm.model.DataArchiveTableConfig; +import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; +import com.oceanbase.odc.service.quartz.util.QuartzCronExpressionUtils; +import com.oceanbase.odc.service.schedule.model.DataArchiveAttributes; +import com.oceanbase.odc.service.schedule.model.DataDeleteAttributes; +import com.oceanbase.odc.service.schedule.model.Schedule; +import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; +import com.oceanbase.odc.service.schedule.model.ScheduleListAttributes; +import com.oceanbase.odc.service.schedule.model.ScheduleListResp; +import com.oceanbase.odc.service.schedule.model.ScheduleType; +import com.oceanbase.odc.service.schedule.model.TriggerConfig; import lombok.NonNull; @@ -55,85 +65,151 @@ public class ScheduleResponseMapperFactory { @Autowired private UserRepository userRepository; + @Autowired - private FlowInstanceRepository flowInstanceRepository; + private DatabaseService databaseService; + @Autowired - private ApprovalPermissionService approvalPermissionService; + private ConnectionService dataSourceService; + @Autowired - private DatabaseService databaseService; + private ScheduleTaskRepository scheduleTaskRepository; @Autowired - private DlmLimiterService dlmLimiterService; + private LatestScheduleTaskLinkRepository latestScheduleTaskLinkRepository; - public ScheduleResponseMapper generate(ScheduleEntity entity) { - return generate(Collections.singletonList(entity)); - } - public ScheduleResponseMapper generateInternalWithoutPermission(@NonNull Collection entities) { - if (entities.isEmpty()) { - return new ScheduleResponseMapper(); - } - Set scheduleIds = entities.stream().map(ScheduleEntity::getId).collect(Collectors.toSet()); - Set creators = entities.stream().map(ScheduleEntity::getCreatorId).collect(Collectors.toSet()); - List userEntities = userRepository.findByUserIds(creators); - Map userEntityMap = userEntities.stream().collect( - Collectors.toMap(UserEntity::getId, userEntity -> userEntity)); - Set databaseIds = entities.stream().map(ScheduleEntity::getDatabaseId).collect(Collectors.toSet()); - Map id2Database = databaseService.listDatabasesByIds(databaseIds).stream().collect( - Collectors.toMap(Database::getId, o -> o)); - - - Map scheduleId2RateLimitConfiguration = - dlmLimiterService.findByOrderIds(scheduleIds).stream().collect( - Collectors.toMap(RateLimitConfiguration::getOrderId, o -> o)); - - - return new ScheduleResponseMapper() - .withGetUserById(userEntityMap::get) - .withGetApproveInstanceIdById(t -> null) - .withGetDatabaseById(id2Database::get) - .withGetCandidatesById(t -> null) - .withGetDLMRateLimitConfigurationById(scheduleId2RateLimitConfiguration::get); + + public ScheduleDetailResp generateScheduleDetailResp(@NonNull Schedule schedule) { + ScheduleDetailResp scheduleDetailResp = new ScheduleDetailResp(); + + scheduleDetailResp.setScheduleId(schedule.getId()); + scheduleDetailResp.setTriggerConfig(schedule.getTriggerConfigJson()); + scheduleDetailResp.setMisfireStrategy(schedule.getMisfireStrategy()); + scheduleDetailResp.setAllowConcurrent(schedule.getAllowConcurrent()); + + scheduleDetailResp.setType(schedule.getScheduleType()); + scheduleDetailResp.setStatus(schedule.getStatus()); + scheduleDetailResp.setCreateTime(schedule.getCreateTime()); + scheduleDetailResp.setUpdateTime(schedule.getUpdateTime()); + scheduleDetailResp.setProjectId(schedule.getProjectId()); + scheduleDetailResp.setDescription(schedule.getDescription()); + + scheduleDetailResp.setNextFireTimes( + QuartzCronExpressionUtils.getNextFiveFireTimes(JsonUtils.fromJson(schedule.getTriggerConfigJson(), + TriggerConfig.class).getCronExpression())); + userRepository.findById(schedule.getCreatorId()) + .ifPresent(o -> scheduleDetailResp.setCreator(new InnerUser(o, null))); + + scheduleDetailResp.setType(schedule.getScheduleType()); + scheduleDetailResp.setParameters(schedule.getParameters()); + + return scheduleDetailResp; } + public List generateListResponse(@NonNull Collection schedules) { - public ScheduleResponseMapper generate(@NonNull Collection entities) { - if (entities.isEmpty()) { - return new ScheduleResponseMapper(); - } - ScheduleResponseMapper scheduleResponseMapper = generateInternalWithoutPermission(entities); - Set scheduleIds = entities.stream().map(ScheduleEntity::getId).collect(Collectors.toSet()); - Set approvableFlowInstanceIds = approvalPermissionService.getApprovableApprovalInstances() - .stream() - .filter(entity -> FlowNodeStatus.EXECUTING == entity.getStatus()) - .map(UserTaskInstanceEntity::getFlowInstanceId).collect(Collectors.toSet()); - Map approveInstanceIdMap = Collections.EMPTY_MAP; - if (!approvableFlowInstanceIds.isEmpty()) { - List flowInstances = flowInstanceRepository.findByFlowInstanceIdsAndTaskType( - approvableFlowInstanceIds, TaskType.ALTER_SCHEDULE); - approveInstanceIdMap = - flowInstances.stream().filter(entity -> entity.getParentInstanceId() != null).collect( - Collectors.toMap(FlowInstanceEntity::getParentInstanceId, FlowInstanceEntity::getId, - (oldValue, newValue) -> oldValue)); + if (schedules.isEmpty()) { + return Collections.emptyList(); } - Map scheduleId2FlowInstanceId = flowInstanceRepository.findByScheduleIdAndStatus(scheduleIds, - FlowStatus.APPROVING).stream().collect( - Collectors.toMap(FlowInstanceEntity::getParentInstanceId, FlowInstanceEntity::getId)); - Map> flowInstanceId2Candidates = - approvalPermissionService.getCandidatesByFlowInstanceIds(scheduleId2FlowInstanceId.values()); - - Map> scheduleId2Candidates = scheduleId2FlowInstanceId.entrySet().stream() - .filter(entry -> flowInstanceId2Candidates.get(entry.getValue()) != null).collect( - Collectors.toMap(Entry::getKey, entry -> flowInstanceId2Candidates.get(entry.getValue()))); + Set scheduleIds = schedules.stream().map(ScheduleEntity::getId).collect(Collectors.toSet()); + + Map scheduleId2ScheduleTaskId = + latestScheduleTaskLinkRepository.findByScheduleIdIn(scheduleIds).stream().collect( + Collectors.toMap(LatestScheduleTaskLinkEntity::getScheduleId, + LatestScheduleTaskLinkEntity::getScheduleTaskId)); + + Map scheduleId2ScheduleTask = + scheduleId2ScheduleTaskId.isEmpty() ? Collections.EMPTY_MAP + : scheduleTaskRepository.findByJobNames( + scheduleId2ScheduleTaskId.values().stream().map(Object::toString).collect( + Collectors.toSet())) + .stream().collect(Collectors.toMap(o -> Long.valueOf(o.getJobName()), o -> o)); + + Map id2Attributes = generateAttributes(schedules); + return schedules.stream().map(o -> { + ScheduleListResp scheduleListResp = new ScheduleListResp(); + scheduleListResp.setScheduleId(o.getId()); + scheduleListResp.setStatus(o.getStatus()); + scheduleListResp.setAttributes(id2Attributes.get(o.getId())); + if (scheduleId2ScheduleTaskId.containsKey(o.getId())) { + ScheduleTaskEntity scheduleTask = scheduleId2ScheduleTask.get(o.getId()); + scheduleListResp.setLatestFireTime(scheduleTask.getFireTime()); + scheduleListResp.setLatestExecutionStatus(scheduleTask.getStatus()); + } + return scheduleListResp; + }).collect(Collectors.toList()); + } - Map scheduleId2RateLimitConfiguration = - dlmLimiterService.findByOrderIds(scheduleIds).stream().collect( - Collectors.toMap(RateLimitConfiguration::getOrderId, o -> o)); + private Map generateAttributes(Collection schedules) { + Map> type2Entity = schedules.stream().collect( + Collectors.groupingBy(ScheduleEntity::getScheduleType)); + Map id2Attributes = new HashMap<>(); + type2Entity.forEach((k, v) -> { + switch (k) { + case DATA_DELETE: { + Set databaseIds = new HashSet<>(); + v.forEach(o -> { + DataDeleteParameters dataDeleteParameters = JsonUtils.fromJson(o.getJobParametersJson(), + DataDeleteParameters.class); + databaseIds.add(dataDeleteParameters.getDatabaseId()); + }); + Map id2Database = getDatabaseByIds(databaseIds).stream().collect( + Collectors.toMap(Database::getId, o -> o)); + + v.forEach(o -> { + DataDeleteAttributes attributes = new DataDeleteAttributes(); + attributes.setSourceDataBaseInfo(id2Database.get(o.getDatabaseId())); + DataDeleteParameters dataDeleteParameters = + JsonUtils.fromJson(o.getJobParametersJson(), DataDeleteParameters.class); + attributes.setTableNames(dataDeleteParameters.getTables().stream().map( + DataArchiveTableConfig::getTableName).collect(Collectors.toList())); + id2Attributes.put(o.getId(), attributes); + }); + break; + } + case DATA_ARCHIVE: { + Set databaseIds = new HashSet<>(); + v.forEach(o -> { + DataArchiveParameters parameters = JsonUtils.fromJson(o.getJobParametersJson(), + DataArchiveParameters.class); + databaseIds.add(parameters.getSourceDatabaseId()); + databaseIds.add(parameters.getTargetDataBaseId()); + }); + Map id2Database = getDatabaseByIds(databaseIds).stream().collect( + Collectors.toMap(Database::getId, o -> o)); + + v.forEach(o -> { + DataArchiveParameters parameters = JsonUtils.fromJson(o.getJobParametersJson(), + DataArchiveParameters.class); + DataArchiveAttributes attributes = new DataArchiveAttributes(); + attributes.setSourceDataBaseInfo(id2Database.get(parameters.getSourceDatabaseId())); + attributes.setTargetDataBaseInfo(id2Database.get(parameters.getTargetDataBaseId())); + id2Attributes.put(o.getId(), attributes); + }); + break; + } + default: + break; + } + }); + return id2Attributes; + } - return scheduleResponseMapper - .withGetApproveInstanceIdById(approveInstanceIdMap::get) - .withGetCandidatesById(scheduleId2Candidates::get) - .withGetDLMRateLimitConfigurationById(scheduleId2RateLimitConfiguration::get); + private List getDatabaseByIds(Set ids) { + List databases = databaseService.listDatabasesByIds(ids); + Set connectionIds = + databases.stream().filter(e -> e.getDataSource() != null && e.getDataSource().getId() != null) + .map(e -> e.getDataSource().getId()).collect(Collectors.toSet()); + Map id2Connection = dataSourceService.innerListByIds(connectionIds) + .stream().collect(Collectors.toMap(ConnectionConfig::getId, o -> o)); + databases.forEach(database -> { + if (id2Connection.containsKey(database.getDataSource().getId())) { + database.setDataSource(id2Connection.get(database.getDataSource().getId())); + } + }); + return databases; } + } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleParameters.java index eb00aa9833..2b3e71c0dd 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleParameters.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleParameters.java @@ -27,6 +27,7 @@ import com.oceanbase.odc.service.flow.task.model.DatabaseChangeParameters; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.OperationType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import lombok.Data; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleTask.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleTask.java index 2c8b54f436..43abd3a54e 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleTask.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AlterScheduleTask.java @@ -18,15 +18,10 @@ import org.flowable.engine.delegate.DelegateExecution; import org.springframework.beans.factory.annotation.Autowired; -import com.alibaba.fastjson.JSON; import com.oceanbase.odc.core.shared.constant.FlowStatus; -import com.oceanbase.odc.core.shared.exception.UnsupportedException; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.service.flow.task.BaseODCFlowTaskDelegate; -import com.oceanbase.odc.service.flow.util.FlowTaskUtil; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.ScheduleStatus; import com.oceanbase.odc.service.task.TaskService; import lombok.extern.slf4j.Slf4j; @@ -37,6 +32,7 @@ * @Descripition: */ @Slf4j +@Deprecated public class AlterScheduleTask extends BaseODCFlowTaskDelegate { @Autowired @@ -52,68 +48,11 @@ protected AlterScheduleResult start(Long taskId, TaskService taskService, Delega AlterScheduleTraceContextHolder.trace(authenticationFacade.currentUser().getId(), taskId); AlterScheduleResult taskResult = new AlterScheduleResult(); log.info("Start to alter schedule task."); - try { - taskService.start(taskId); - AlterScheduleParameters parameters = FlowTaskUtil.getAlterScheduleTaskParameters(execution); - ScheduleEntity scheduleEntity = - scheduleService.nullSafeGetById(parameters.getTaskId()); - scheduleEntity.setModifierId(FlowTaskUtil.getTaskCreator(execution).getCreatorId()); - log.info("operation type = {}", parameters.getOperationType()); - switch (parameters.getOperationType()) { - case CREATE: { - scheduleService.enable(scheduleEntity); - break; - } - case UPDATE: { - scheduleEntity.setMisfireStrategy(parameters.getMisfireStrategy()); - scheduleEntity.setAllowConcurrent(parameters.getAllowConcurrent()); - scheduleEntity.setDescription(parameters.getDescription()); - scheduleEntity.setTriggerConfigJson(JSON.toJSONString(parameters.getTriggerConfig())); - scheduleEntity.setJobParametersJson(JSON.toJSONString(parameters.getScheduleTaskParameters())); - scheduleService.updateJobData(scheduleEntity); - break; - } - case PAUSE: { - if (scheduleEntity.getStatus() != ScheduleStatus.ENABLED) { - throw new RuntimeException( - String.format("Pause schedule not allowed,schedule status=%s", - scheduleEntity.getStatus())); - } - scheduleService.pause(scheduleEntity); - break; - } - case TERMINATION: - scheduleService.terminate(scheduleEntity); - break; - case RESUME: - if (scheduleEntity.getStatus() != ScheduleStatus.PAUSE) { - throw new RuntimeException( - String.format("Resume schedule not allowed,schedule status=%s", - scheduleEntity.getStatus())); - } - scheduleService.resume(scheduleEntity); - break; - default: - throw new UnsupportedException( - String.format("Unsupported operation type,type=%s", parameters.getOperationType())); - } - taskResult.setParameters(parameters); - taskService.succeed(taskId, taskResult); - isSuccessful = true; - log.info("Alter schedule succeed,taskId={}", taskId); - return taskResult; - } catch (Exception e) { - isFailure = true; - AlterScheduleParameters parameters = FlowTaskUtil.getAlterScheduleTaskParameters( - execution); - if (parameters.getOperationType() == OperationType.CREATE) { - scheduleService.updateStatusById(parameters.getTaskId(), - ScheduleStatus.TERMINATION); - } - taskService.fail(taskId, 0, taskResult); - log.warn("Alter schedule failed,error={}", e.getMessage()); - return taskResult; - } + taskService.start(taskId); + taskService.succeed(taskId, taskResult); + isSuccessful = true; + log.info("Alter schedule succeed,taskId={}", taskId); + return taskResult; } @Override diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/SqlPlanPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/SqlPlanPreprocessor.java deleted file mode 100644 index 1861940509..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/SqlPlanPreprocessor.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2023 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.oceanbase.odc.service.schedule.flowtask; - -import java.util.Set; - -import org.quartz.CronExpression; -import org.springframework.beans.factory.annotation.Autowired; - -import com.oceanbase.odc.common.json.JsonUtils; -import com.oceanbase.odc.core.shared.PreConditions; -import com.oceanbase.odc.core.shared.constant.ErrorCodes; -import com.oceanbase.odc.core.shared.constant.FlowStatus; -import com.oceanbase.odc.core.shared.exception.BadRequestException; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; -import com.oceanbase.odc.service.flow.FlowInstanceService; -import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; -import com.oceanbase.odc.service.flow.processor.Preprocessor; -import com.oceanbase.odc.service.flow.processor.ScheduleTaskPreprocessor; -import com.oceanbase.odc.service.flow.task.model.DatabaseChangeParameters; -import com.oceanbase.odc.service.flow.task.model.FlowTaskProperties; -import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; -import com.oceanbase.odc.service.quartz.util.QuartzCronExpressionUtils; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.JobType; -import com.oceanbase.odc.service.schedule.model.ScheduleStatus; -import com.oceanbase.odc.service.schedule.model.TriggerConfig; - -/** - * @Author:tinker - * @Date: 2023/5/25 11:40 - * @Descripition: - */ - -@ScheduleTaskPreprocessor(type = JobType.SQL_PLAN) -public class SqlPlanPreprocessor implements Preprocessor { - - @Autowired - private AuthenticationFacade authenticationFacade; - @Autowired - private ScheduleService scheduleService; - @Autowired - private FlowInstanceService flowInstanceService; - @Autowired - private FlowTaskProperties flowTaskProperties; - - @Override - public void process(CreateFlowInstanceReq req) { - - AlterScheduleParameters parameters = (AlterScheduleParameters) req.getParameters(); - TriggerConfig triggerConfig = parameters.getTriggerConfig(); - - // find approving instance before create new flow instance. - if (parameters.getTaskId() != null) { - checkAlterSchedule(parameters.getTaskId()); - } - - switch (parameters.getOperationType()) { - case CREATE: { - // pre-create schedule(order) - checkSqlContent(parameters); - checkCronExpression(triggerConfig.getCronExpression()); - ScheduleEntity scheduleEntity = new ScheduleEntity(); - scheduleEntity.setConnectionId(req.getConnectionId()); - scheduleEntity.setDatabaseName(req.getDatabaseName()); - scheduleEntity.setProjectId(req.getProjectId()); - scheduleEntity.setDatabaseId(req.getDatabaseId()); - scheduleEntity.setJobType(parameters.getType()); - scheduleEntity.setStatus(ScheduleStatus.APPROVING); - scheduleEntity.setAllowConcurrent(parameters.getAllowConcurrent()); - scheduleEntity.setMisfireStrategy(parameters.getMisfireStrategy()); - scheduleEntity.setJobParametersJson(JsonUtils.toJson(parameters.getScheduleTaskParameters())); - scheduleEntity.setTriggerConfigJson(JsonUtils.toJson(triggerConfig)); - scheduleEntity.setCreatorId(authenticationFacade.currentUser().id()); - scheduleEntity.setOrganizationId(authenticationFacade.currentOrganizationId()); - scheduleEntity.setModifierId(scheduleEntity.getCreatorId()); - scheduleEntity.setDescription(req.getDescription()); - scheduleEntity = scheduleService.create(scheduleEntity); - parameters.setTaskId(scheduleEntity.getId()); - break; - } - case UPDATE: { - checkSqlContent(parameters); - checkCronExpression(triggerConfig.getCronExpression()); - parameters.setDescription(req.getDescription()); - break; - } - default: { - ScheduleEntity scheduleEntity = scheduleService.nullSafeGetById(parameters.getTaskId()); - if (scheduleEntity.getJobType() == JobType.SQL_PLAN) { - parameters.setScheduleTaskParameters(JsonUtils.fromJson(scheduleEntity.getJobParametersJson(), - DatabaseChangeParameters.class)); - parameters.setType(JobType.SQL_PLAN); - parameters.setTriggerConfig( - JsonUtils.fromJson(scheduleEntity.getTriggerConfigJson(), TriggerConfig.class)); - parameters.setDescription(scheduleEntity.getDescription()); - } - break; - } - } - req.setParentFlowInstanceId(parameters.getTaskId()); - } - - private void checkSqlContent(AlterScheduleParameters parameters) { - DatabaseChangeParameters taskParameters = (DatabaseChangeParameters) parameters.getScheduleTaskParameters(); - PreConditions.maxLength(taskParameters.getSqlContent(), "sql content", - flowTaskProperties.getSqlContentMaxLength()); - } - - private void checkAlterSchedule(Long scheduleId) { - Set approvingAlterScheduleIds = flowInstanceService.listAlterScheduleIdsByScheduleIdAndStatus( - scheduleId, FlowStatus.APPROVING); - PreConditions.validNoDuplicatedAlterSchedule("ScheduleId", scheduleId, - () -> approvingAlterScheduleIds != null && approvingAlterScheduleIds.size() > 0); - } - - private void checkCronExpression(String cron) { - try { - cron = QuartzCronExpressionUtils.adaptCronExpression(cron); - new CronExpression(cron); - } catch (Exception e) { - throw new BadRequestException(ErrorCodes.InvalidCronExpression, - new Object[] {e.getMessage()}, - e.getMessage()); - } - } - - -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/AbstractDlmJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/AbstractDlmJob.java index f42012bf88..7507e728ac 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/AbstractDlmJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/AbstractDlmJob.java @@ -16,36 +16,21 @@ package com.oceanbase.odc.service.schedule.job; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import org.quartz.JobExecutionContext; import com.fasterxml.jackson.core.type.TypeReference; import com.oceanbase.odc.common.json.JsonUtils; -import com.oceanbase.odc.common.util.StringUtils; -import com.oceanbase.odc.core.shared.constant.TaskStatus; -import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.metadb.schedule.ScheduleTaskRepository; import com.oceanbase.odc.service.common.util.SpringContextUtil; import com.oceanbase.odc.service.connection.database.DatabaseService; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.connection.model.ConnectionConfig; -import com.oceanbase.odc.service.dlm.DLMJobFactory; -import com.oceanbase.odc.service.dlm.DLMService; -import com.oceanbase.odc.service.dlm.DLMTableStructureSynchronizer; import com.oceanbase.odc.service.dlm.DataSourceInfoMapper; import com.oceanbase.odc.service.dlm.DlmLimiterService; -import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; -import com.oceanbase.odc.service.dlm.model.DlmTableUnit; -import com.oceanbase.odc.service.dlm.model.DlmTableUnitParameters; -import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; -import com.oceanbase.odc.service.dlm.utils.DataArchiveConditionUtil; -import com.oceanbase.odc.service.dlm.utils.DlmJobIdUtil; import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.DlmTableUnitStatistic; import com.oceanbase.odc.service.task.config.TaskFrameworkEnabledProperties; import com.oceanbase.odc.service.task.constants.JobParametersKeyConstants; import com.oceanbase.odc.service.task.executor.task.DataArchiveTask; @@ -54,10 +39,6 @@ import com.oceanbase.odc.service.task.schedule.SingleJobProperties; import com.oceanbase.odc.service.task.service.TaskFrameworkService; import com.oceanbase.tools.migrator.common.configure.DataSourceInfo; -import com.oceanbase.tools.migrator.common.enums.JobType; -import com.oceanbase.tools.migrator.common.exception.JobException; -import com.oceanbase.tools.migrator.job.Job; -import com.oceanbase.tools.migrator.task.CheckMode; import lombok.extern.slf4j.Slf4j; @@ -70,149 +51,29 @@ public abstract class AbstractDlmJob implements OdcJob { public final ScheduleTaskRepository scheduleTaskRepository; - public final DLMJobFactory jobFactory; public final DatabaseService databaseService; public final ScheduleService scheduleService; public final DlmLimiterService limiterService; - public final DLMService dlmService; public JobScheduler jobScheduler = null; public final TaskFrameworkEnabledProperties taskFrameworkProperties; public final TaskFrameworkService taskFrameworkService; - private Job job; - private boolean isInterrupted = false; - private Thread monitor; public AbstractDlmJob() { scheduleTaskRepository = SpringContextUtil.getBean(ScheduleTaskRepository.class); - jobFactory = SpringContextUtil.getBean(DLMJobFactory.class); databaseService = SpringContextUtil.getBean(DatabaseService.class); scheduleService = SpringContextUtil.getBean(ScheduleService.class); limiterService = SpringContextUtil.getBean(DlmLimiterService.class); taskFrameworkProperties = SpringContextUtil.getBean(TaskFrameworkEnabledProperties.class); taskFrameworkService = SpringContextUtil.getBean(TaskFrameworkService.class); - dlmService = SpringContextUtil.getBean(DLMService.class); if (taskFrameworkProperties.isEnabled()) { jobScheduler = SpringContextUtil.getBean(JobScheduler.class); } } - public void executeTask(Long taskId, List dlmTableUnits, Long timeoutMillis) { - initMonitor(taskId, timeoutMillis); - scheduleTaskRepository.updateStatusById(taskId, TaskStatus.RUNNING); - log.info("Task is ready,taskId={}", taskId); - for (DlmTableUnit dlmTableUnit : dlmTableUnits) { - if (isInterrupted) { - log.info("Task interrupted and will exit.TaskId={}", taskId); - continue; - } - if (dlmTableUnit.getStatus() == TaskStatus.DONE) { - log.info("The task unit had been completed,taskId={},tableName={}", taskId, - dlmTableUnit.getTableName()); - continue; - } - if (dlmTableUnit.getType() == JobType.MIGRATE) { - try { - DLMTableStructureSynchronizer.sync(dlmTableUnit.getSourceDatasourceInfo(), - dlmTableUnit.getTargetDatasourceInfo(), dlmTableUnit.getTableName(), - dlmTableUnit.getTargetTableName(), - dlmTableUnit.getParameters().getSyncDBObjectType()); - } catch (Exception e) { - log.warn("Sync table structure failed,tableName={}", dlmTableUnit.getTableName(), e); - dlmService.updateStatusByDlmTableUnitId(dlmTableUnit.getDlmTableUnitId(), TaskStatus.FAILED); - continue; - } - } - try { - job = jobFactory.createJob(dlmTableUnit); - log.info("Create dlm job succeed,taskId={},task parameters={}", taskId, dlmTableUnit); - } catch (Exception e) { - log.warn("Create dlm job failed,taskId={},tableName={},errorMessage={}", taskId, - dlmTableUnit.getTableName(), e); - dlmService.updateStatusByDlmTableUnitId(dlmTableUnit.getDlmTableUnitId(), TaskStatus.FAILED); - continue; - } - try { - dlmService.updateStatusByDlmTableUnitId(dlmTableUnit.getDlmTableUnitId(), TaskStatus.RUNNING); - job.run(); - dlmService.updateStatusByDlmTableUnitId(dlmTableUnit.getDlmTableUnitId(), TaskStatus.DONE); - log.info("DLM job succeed,taskId={},unitId={}", taskId, dlmTableUnit.getDlmTableUnitId()); - } catch (JobException e) { - // used to stop several sub-threads. - if (isInterrupted) { - log.info("Data archive task is Interrupted,taskId={}", taskId); - dlmService.updateStatusByDlmTableUnitId(dlmTableUnit.getDlmTableUnitId(), TaskStatus.CANCELED); - } else { - log.error("Data archive task is failed,taskId={},errorMessage={}", taskId, e); - dlmService.updateStatusByDlmTableUnitId(dlmTableUnit.getDlmTableUnitId(), TaskStatus.FAILED); - } - } - } - } - - public TaskStatus getTaskStatus(Long scheduleTaskId) { - return dlmService.getTaskStatus(scheduleTaskId); - } - - public List getTaskUnits(ScheduleTaskEntity taskEntity) { - // Resume or retry an existing task. - List dlmJobs = dlmService.findByScheduleTaskId(taskEntity.getId()); - if (!dlmJobs.isEmpty()) { - return dlmJobs; - } - return splitTask(taskEntity); - } - - public List splitTask(ScheduleTaskEntity taskEntity) { - - DataArchiveParameters parameters = JsonUtils.fromJson(taskEntity.getParametersJson(), - DataArchiveParameters.class); - List dlmTableUnits = new LinkedList<>(); - parameters.getTables().forEach(table -> { - String condition = StringUtils.isNotEmpty(table.getConditionExpression()) - ? DataArchiveConditionUtil.parseCondition(table.getConditionExpression(), parameters.getVariables(), - taskEntity.getFireTime()) - : ""; - DlmTableUnit dlmTableUnit = new DlmTableUnit(); - dlmTableUnit.setScheduleTaskId(taskEntity.getId()); - DlmTableUnitParameters jobParameter = new DlmTableUnitParameters(); - RateLimitConfiguration limiterConfig = - limiterService.getByOrderIdOrElseDefaultConfig(Long.parseLong(taskEntity.getJobName())); - jobParameter.setMigrateRule(condition); - jobParameter.setCheckMode(CheckMode.MULTIPLE_GET); - jobParameter.setGeneratorBatchSize(parameters.getScanBatchSize()); - jobParameter.setShardingStrategy(parameters.getShardingStrategy()); - jobParameter.setReaderTaskCount(parameters.getReadThreadCount()); - jobParameter.setWriterTaskCount(parameters.getWriteThreadCount()); - jobParameter.setReaderBatchSize(limiterConfig.getBatchSize()); - jobParameter.setWriterBatchSize(limiterConfig.getBatchSize()); - jobParameter.setMigrationInsertAction(parameters.getMigrationInsertAction()); - jobParameter.setSyncDBObjectType(parameters.getSyncTableStructure()); - jobParameter.setMigratePartitions(table.getPartitions()); - dlmTableUnit.setParameters(jobParameter); - dlmTableUnit.setDlmTableUnitId( - DlmJobIdUtil.generateHistoryJobId(taskEntity.getJobName(), taskEntity.getJobGroup(), - taskEntity.getId(), - dlmTableUnits.size())); - dlmTableUnit.setTableName(table.getTableName()); - dlmTableUnit.setTargetTableName(table.getTargetTableName()); - dlmTableUnit.setSourceDatasourceInfo(getDataSourceInfo(parameters.getSourceDatabaseId())); - dlmTableUnit.setTargetDatasourceInfo(getDataSourceInfo(parameters.getTargetDataBaseId())); - dlmTableUnit.getSourceDatasourceInfo().setQueryTimeout(parameters.getQueryTimeout()); - dlmTableUnit.getTargetDatasourceInfo().setQueryTimeout(parameters.getQueryTimeout()); - dlmTableUnit.setFireTime(taskEntity.getFireTime()); - dlmTableUnit.setStatus(TaskStatus.PREPARING); - dlmTableUnit.setType(JobType.MIGRATE); - dlmTableUnit.setStatistic(new DlmTableUnitStatistic()); - dlmTableUnits.add(dlmTableUnit); - }); - dlmService.createDlmTableUnits(dlmTableUnits); - return dlmTableUnits; - } - public DataSourceInfo getDataSourceInfo(Long databaseId) { Database db = databaseService.detail(databaseId); ConnectionConfig config = databaseService.findDataSourceForConnectById(databaseId); @@ -271,32 +132,7 @@ public void after(JobExecutionContext context) { @Override public void interrupt() { - isInterrupted = true; - if (job != null) { - job.stop(); - log.info("Job will be interrupted,jobId={}", job.getJobMeta().getJobId()); - } - } - private void initMonitor(Long scheduleTaskId, Long timeoutMillis) { - if (timeoutMillis == null) { - return; - } - monitor = new Thread(() -> { - long elapsedTime = 0L; - while (elapsedTime < timeoutMillis) { - try { - Thread.sleep(10000); - elapsedTime += 10000; - } catch (InterruptedException e) { - return; - } - } - log.info("Job execution timed out,initiating job suspension."); - this.interrupt(); - }); - monitor.setName(String.format("%s-%s", "TimeoutMonitor", scheduleTaskId)); - monitor.setDaemon(true); - monitor.start(); } + } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveDeleteJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveDeleteJob.java index 3721f1e997..5fe138e347 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveDeleteJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveDeleteJob.java @@ -15,7 +15,6 @@ */ package com.oceanbase.odc.service.schedule.job; -import java.util.List; import java.util.Optional; import org.quartz.JobExecutionContext; @@ -24,8 +23,6 @@ import com.oceanbase.odc.core.shared.constant.TaskStatus; import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; -import com.oceanbase.odc.service.dlm.model.DlmTableUnit; -import com.oceanbase.odc.service.dlm.utils.DlmJobIdUtil; import com.oceanbase.odc.service.schedule.model.DataArchiveClearParameters; import com.oceanbase.tools.migrator.common.enums.JobType; @@ -66,35 +63,13 @@ public void executeJob(JobExecutionContext context) { return; } - // execute in task framework. - if (taskFrameworkProperties.isEnabled()) { - DLMJobReq parameters = getDLMJobReq(dataArchiveTask.getJobId()); - parameters.setJobType(JobType.DELETE); - parameters.setScheduleTaskId(taskEntity.getId()); - Long jobId = publishJob(parameters, dataArchiveParameters.getTimeoutMillis()); - log.info("Publish DLM job to task framework succeed,scheduleTaskId={},jobIdentity={}", taskEntity.getId(), - jobId); - scheduleTaskRepository.updateJobIdById(taskEntity.getId(), jobId); - scheduleTaskRepository.updateTaskResult(taskEntity.getId(), JsonUtils.toJson(parameters)); - return; - } - List dlmTableUnits = dlmService.findByScheduleTaskId(taskEntity.getId()); - if (dlmTableUnits.isEmpty()) { - dlmTableUnits = dlmService.findByScheduleTaskId(dataArchiveTask.getId()); - for (int i = 0; i < dlmTableUnits.size(); i++) { - dlmTableUnits.get(i) - .setDlmTableUnitId( - DlmJobIdUtil.generateHistoryJobId(taskEntity.getJobName(), taskEntity.getJobGroup(), - taskEntity.getId(), - i)); - dlmTableUnits.get(i).setType(JobType.DELETE); - dlmTableUnits.get(i).setStatus(TaskStatus.PREPARING); - dlmTableUnits.get(i).setScheduleTaskId(taskEntity.getId()); - } - dlmService.createDlmTableUnits(dlmTableUnits); - } - executeTask(taskEntity.getId(), dlmTableUnits, dataArchiveParameters.getTimeoutMillis()); - TaskStatus taskStatus = getTaskStatus(taskEntity.getId()); - scheduleTaskRepository.updateStatusById(taskEntity.getId(), taskStatus); + DLMJobReq parameters = getDLMJobReq(dataArchiveTask.getJobId()); + parameters.setJobType(JobType.DELETE); + parameters.setScheduleTaskId(taskEntity.getId()); + Long jobId = publishJob(parameters, dataArchiveParameters.getTimeoutMillis()); + log.info("Publish DLM job to task framework succeed,scheduleTaskId={},jobIdentity={}", taskEntity.getId(), + jobId); + scheduleTaskRepository.updateJobIdById(taskEntity.getId(), jobId); + scheduleTaskRepository.updateTaskResult(taskEntity.getId(), JsonUtils.toJson(parameters)); } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveJob.java index 9326dcc478..0f296ed3e8 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveJob.java @@ -15,17 +15,13 @@ */ package com.oceanbase.odc.service.schedule.job; -import java.util.List; - import org.quartz.JobExecutionContext; import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.common.util.StringUtils; -import com.oceanbase.odc.core.shared.constant.TaskStatus; import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; import com.oceanbase.odc.service.dlm.model.DataArchiveTableConfig; -import com.oceanbase.odc.service.dlm.model.DlmTableUnit; import com.oceanbase.odc.service.dlm.utils.DataArchiveConditionUtil; import com.oceanbase.tools.migrator.common.enums.JobType; @@ -40,29 +36,7 @@ public class DataArchiveJob extends AbstractDlmJob { @Override public void executeJob(JobExecutionContext context) { - // execute in task framework. - if (taskFrameworkProperties.isEnabled()) { - executeInTaskFramework(context); - return; - } - - ScheduleTaskEntity taskEntity = (ScheduleTaskEntity) context.getResult(); - - List dlmTableUnits = getTaskUnits(taskEntity); - DataArchiveParameters dataArchiveParameters = JsonUtils.fromJson(taskEntity.getParametersJson(), - DataArchiveParameters.class); - executeTask(taskEntity.getId(), dlmTableUnits, dataArchiveParameters.getTimeoutMillis()); - TaskStatus taskStatus = getTaskStatus(taskEntity.getId()); - scheduleTaskRepository.updateStatusById(taskEntity.getId(), taskStatus); - - DataArchiveParameters parameters = JsonUtils.fromJson(taskEntity.getParametersJson(), - DataArchiveParameters.class); - - if (taskStatus == TaskStatus.DONE && parameters.isDeleteAfterMigration()) { - log.info("Start to create clear job,scheduleTaskId={}", taskEntity.getId()); - scheduleService.dataArchiveDelete(Long.parseLong(taskEntity.getJobName()), taskEntity.getId()); - log.info("Clear job is created,"); - } + executeInTaskFramework(context); } private void executeInTaskFramework(JobExecutionContext context) { diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveRollbackJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveRollbackJob.java index 1a404e9ca6..a6156f7574 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveRollbackJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataArchiveRollbackJob.java @@ -15,7 +15,6 @@ */ package com.oceanbase.odc.service.schedule.job; -import java.util.List; import java.util.Optional; import org.quartz.JobExecutionContext; @@ -24,8 +23,6 @@ import com.oceanbase.odc.core.shared.constant.TaskStatus; import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; -import com.oceanbase.odc.service.dlm.model.DlmTableUnit; -import com.oceanbase.odc.service.dlm.utils.DlmJobIdUtil; import com.oceanbase.odc.service.schedule.model.DataArchiveRollbackParameters; import com.oceanbase.tools.migrator.common.configure.DataSourceInfo; import com.oceanbase.tools.migrator.common.enums.JobType; @@ -57,52 +54,25 @@ public void executeJob(JobExecutionContext context) { scheduleTaskRepository.updateStatusById(taskEntity.getId(), TaskStatus.FAILED); return; } - ScheduleTaskEntity dataArchiveTask = dataArchiveTaskOption.get(); DataArchiveParameters dataArchiveParameters = JsonUtils.fromJson(dataArchiveTask.getParametersJson(), DataArchiveParameters.class); // execute in task framework. - if (taskFrameworkProperties.isEnabled()) { - DLMJobReq parameters = getDLMJobReq(dataArchiveTask.getJobId()); - parameters.setJobType(JobType.ROLLBACK); - DataSourceInfo tempDataSource = parameters.getSourceDs(); - parameters.setSourceDs(parameters.getTargetDs()); - parameters.setTargetDs(tempDataSource); - parameters.getTables().forEach(o -> { - String temp = o.getTableName(); - o.setTableName(o.getTargetTableName()); - o.setTargetTableName(temp); - }); - parameters.setScheduleTaskId(taskEntity.getId()); - Long jobId = publishJob(parameters, dataArchiveParameters.getTimeoutMillis()); - log.info("Publish DLM job to task framework succeed,scheduleTaskId={},jobIdentity={}", taskEntity.getId(), - jobId); - scheduleTaskRepository.updateJobIdById(taskEntity.getId(), jobId); - scheduleTaskRepository.updateTaskResult(taskEntity.getId(), JsonUtils.toJson(parameters)); - return; - } - // prepare tasks for rollback - List dlmTableUnits = dlmService.findByScheduleTaskId(dataArchiveTask.getId()); - for (int i = 0; i < dlmTableUnits.size(); i++) { - DlmTableUnit dlmTableUnit = dlmTableUnits.get(i); - DataSourceInfo temp = dlmTableUnit.getSourceDatasourceInfo(); - dlmTableUnit.setDlmTableUnitId( - DlmJobIdUtil.generateHistoryJobId(taskEntity.getJobName(), taskEntity.getJobGroup(), - taskEntity.getId(), - i)); - dlmTableUnit.setSourceDatasourceInfo(dlmTableUnit.getTargetDatasourceInfo()); - dlmTableUnit.setTargetDatasourceInfo(temp); - String tmp = dlmTableUnit.getTableName(); - dlmTableUnit.setTableName(dlmTableUnit.getTargetTableName()); - dlmTableUnit.setTargetTableName(tmp); - dlmTableUnit.setType(JobType.ROLLBACK); - dlmTableUnit.setStatus( - dlmTableUnit.getStatus() == TaskStatus.PREPARING ? TaskStatus.DONE : TaskStatus.PREPARING); - dlmTableUnits.get(i).setScheduleTaskId(taskEntity.getId()); - } - dlmService.createDlmTableUnits(dlmTableUnits); - executeTask(taskEntity.getId(), dlmTableUnits, dataArchiveParameters.getTimeoutMillis()); - TaskStatus taskStatus = getTaskStatus(taskEntity.getId()); - scheduleTaskRepository.updateStatusById(taskEntity.getId(), taskStatus); + DLMJobReq parameters = getDLMJobReq(dataArchiveTask.getJobId()); + parameters.setJobType(JobType.ROLLBACK); + DataSourceInfo tempDataSource = parameters.getSourceDs(); + parameters.setSourceDs(parameters.getTargetDs()); + parameters.setTargetDs(tempDataSource); + parameters.getTables().forEach(o -> { + String temp = o.getTableName(); + o.setTableName(o.getTargetTableName()); + o.setTargetTableName(temp); + }); + parameters.setScheduleTaskId(taskEntity.getId()); + Long jobId = publishJob(parameters, dataArchiveParameters.getTimeoutMillis()); + log.info("Publish DLM job to task framework succeed,scheduleTaskId={},jobIdentity={}", taskEntity.getId(), + jobId); + scheduleTaskRepository.updateJobIdById(taskEntity.getId(), jobId); + scheduleTaskRepository.updateTaskResult(taskEntity.getId(), JsonUtils.toJson(parameters)); } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataDeleteJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataDeleteJob.java index 25dd5e0741..84fa9040dc 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataDeleteJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/DataDeleteJob.java @@ -15,26 +15,15 @@ */ package com.oceanbase.odc.service.schedule.job; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; - import org.quartz.JobExecutionContext; import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.common.util.StringUtils; -import com.oceanbase.odc.core.shared.constant.TaskStatus; import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.service.dlm.model.DataArchiveTableConfig; import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; -import com.oceanbase.odc.service.dlm.model.DlmTableUnit; -import com.oceanbase.odc.service.dlm.model.DlmTableUnitParameters; -import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; import com.oceanbase.odc.service.dlm.utils.DataArchiveConditionUtil; -import com.oceanbase.odc.service.dlm.utils.DlmJobIdUtil; -import com.oceanbase.odc.service.schedule.model.DlmTableUnitStatistic; import com.oceanbase.tools.migrator.common.enums.JobType; -import com.oceanbase.tools.migrator.task.CheckMode; import lombok.extern.slf4j.Slf4j; @@ -49,69 +38,7 @@ public class DataDeleteJob extends AbstractDlmJob { @Override public void executeJob(JobExecutionContext context) { - - ScheduleTaskEntity taskEntity = (ScheduleTaskEntity) context.getResult(); - - // execute in task framework. - if (taskFrameworkProperties.isEnabled()) { - executeInTaskFramework(context); - return; - } - - List dlmTasks = getTaskUnits(taskEntity); - DataDeleteParameters params = JsonUtils.fromJson(taskEntity.getParametersJson(), - DataDeleteParameters.class); - executeTask(taskEntity.getId(), dlmTasks, params.getTimeoutMillis()); - TaskStatus taskStatus = getTaskStatus(taskEntity.getId()); - scheduleTaskRepository.updateStatusById(taskEntity.getId(), taskStatus); - } - - @Override - public List splitTask(ScheduleTaskEntity taskEntity) { - - DataDeleteParameters parameters = JsonUtils.fromJson(taskEntity.getParametersJson(), - DataDeleteParameters.class); - List dlmTasks = new LinkedList<>(); - parameters.getTables().forEach(table -> { - String condition = StringUtils.isNotEmpty(table.getConditionExpression()) - ? DataArchiveConditionUtil.parseCondition(table.getConditionExpression(), parameters.getVariables(), - taskEntity.getFireTime()) - : ""; - DlmTableUnit dlmTableUnit = new DlmTableUnit(); - dlmTableUnit.setScheduleTaskId(taskEntity.getId()); - dlmTableUnit.setDlmTableUnitId( - DlmJobIdUtil.generateHistoryJobId(taskEntity.getJobName(), taskEntity.getJobGroup(), - taskEntity.getId(), - dlmTasks.size())); - dlmTableUnit.setTableName(table.getTableName()); - dlmTableUnit.setTargetTableName(table.getTargetTableName()); - dlmTableUnit.setSourceDatasourceInfo(getDataSourceInfo(parameters.getDatabaseId())); - dlmTableUnit.setTargetDatasourceInfo( - Objects.isNull(parameters.getTargetDatabaseId()) ? dlmTableUnit.getSourceDatasourceInfo() - : getDataSourceInfo(parameters.getTargetDatabaseId())); - dlmTableUnit.getSourceDatasourceInfo().setQueryTimeout(parameters.getQueryTimeout()); - dlmTableUnit.getTargetDatasourceInfo().setQueryTimeout(parameters.getQueryTimeout()); - dlmTableUnit.setFireTime(taskEntity.getFireTime()); - DlmTableUnitParameters parameter = new DlmTableUnitParameters(); - parameter.setMigrateRule(condition); - parameter.setCheckMode(CheckMode.MULTIPLE_GET); - parameter.setGeneratorBatchSize(parameters.getScanBatchSize()); - parameter.setReaderTaskCount(parameters.getReadThreadCount()); - parameter.setWriterTaskCount(parameters.getWriteThreadCount()); - RateLimitConfiguration limiterConfig = - limiterService.getByOrderIdOrElseDefaultConfig(Long.parseLong(taskEntity.getJobName())); - parameter.setReaderBatchSize(limiterConfig.getBatchSize()); - parameter.setWriterBatchSize(limiterConfig.getBatchSize()); - parameter.setMigratePartitions(table.getPartitions()); - dlmTableUnit.setParameters(parameter); - dlmTableUnit.setStatus(TaskStatus.PREPARING); - dlmTableUnit.setStatistic(new DlmTableUnitStatistic()); - JobType jobType = parameters.getNeedCheckBeforeDelete() ? JobType.DELETE : JobType.QUICK_DELETE; - dlmTableUnit.setType(parameters.getDeleteByUniqueKey() ? jobType : JobType.DEIRECT_DELETE); - dlmTasks.add(dlmTableUnit); - }); - dlmService.createDlmTableUnits(dlmTasks); - return dlmTasks; + executeInTaskFramework(context); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/PartitionPlanJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/PartitionPlanJob.java index 886b4ea828..d8319aceb2 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/PartitionPlanJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/PartitionPlanJob.java @@ -46,7 +46,7 @@ import com.oceanbase.odc.service.partitionplan.model.PartitionPlanTableConfig; import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.session.factory.DefaultConnectSessionFactory; import lombok.extern.slf4j.Slf4j; @@ -155,7 +155,7 @@ private void submitSubDatabaseChangeTask(Long parentFlowInstanceId, Long databas } taskParameters.setSqlContent(sqlContent.toString()); taskParameters.setTimeoutMillis(timeoutMillis); - taskParameters.setParentJobType(JobType.PARTITION_PLAN); + taskParameters.setParentScheduleType(ScheduleType.PARTITION_PLAN); CreateFlowInstanceReq flowInstanceReq = new CreateFlowInstanceReq(); flowInstanceReq.setParameters(taskParameters); flowInstanceReq.setTaskType(TaskType.ASYNC); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/SqlPlanJob.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/SqlPlanJob.java index 3fd07e58bc..01288a04ce 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/SqlPlanJob.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/job/SqlPlanJob.java @@ -30,8 +30,7 @@ import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; import com.oceanbase.odc.service.flow.model.FlowInstanceDetailResp; import com.oceanbase.odc.service.flow.task.model.DatabaseChangeParameters; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import lombok.extern.slf4j.Slf4j; @@ -49,18 +48,10 @@ public void execute(JobExecutionContext context) { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); ScheduleEntity scheduleEntity = JSON.parseObject(JSON.toJSONString(jobDataMap), ScheduleEntity.class); - if (!scheduleEntity.getAllowConcurrent()) { - ScheduleService scheduleService = SpringContextUtil.getBean(ScheduleService.class); - if (scheduleService.hasExecutingAsyncTask(scheduleEntity)) { - log.info("Concurrent execution is not allowed and wait for next time,job key={},fire time={}", - context.getJobDetail().getKey(), context.getFireTime()); - return; - } - } DatabaseChangeParameters taskParameters = JsonUtils.fromJson(scheduleEntity.getJobParametersJson(), DatabaseChangeParameters.class); - taskParameters.setParentJobType(JobType.SQL_PLAN); + taskParameters.setParentScheduleType(ScheduleType.SQL_PLAN); CreateFlowInstanceReq flowInstanceReq = new CreateFlowInstanceReq(); flowInstanceReq.setParameters(taskParameters); flowInstanceReq.setTaskType(TaskType.ASYNC); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java index f842e24f98..b7dba239f3 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java @@ -16,6 +16,7 @@ package com.oceanbase.odc.service.schedule.model; import org.quartz.JobDataMap; +import org.quartz.JobKey; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; @@ -30,10 +31,7 @@ @Data public class CreateQuartzJobReq { - // It represents the owner of the job. - private Long scheduleId; - - private JobType type; + private JobKey jobKey; private Boolean allowConcurrent = false; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java new file mode 100644 index 0000000000..7e81a6df85 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.oceanbase.odc.service.schedule.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonProperty.Access; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; +import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/5/27 18:42 + * @Descripition: + */ + + +@Data +public class CreateScheduleReq { + + + @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "type") + @JsonSubTypes(value = { + @JsonSubTypes.Type(value = DataArchiveParameters.class, name = "DATA_ARCHIVE"), + @JsonSubTypes.Type(value = DataDeleteParameters.class, name = "DATA_DELETE") + }) + private ScheduleTaskParameters parameters; + + // DATA_ARCHIVE、DATA_DELETE、PARTITION_PLAN + private ScheduleType type; + + private TriggerConfig triggerConfig; + + private String description; + + /** + * Followings are filled by aspect + * {@link com.oceanbase.odc.service.schedule.processor.CreateScheduleAspect} + */ + @JsonProperty(access = Access.READ_ONLY) + private Long projectId; + @JsonProperty(access = Access.READ_ONLY) + private String projectName; + @JsonProperty(access = Access.READ_ONLY) + private Long databaseId; + @JsonProperty(access = Access.READ_ONLY) + private String databaseName; + @JsonProperty(access = Access.READ_ONLY) + private Long connectionId; + @JsonProperty(access = Access.READ_ONLY) + private String connectionName; + @JsonProperty(access = Access.READ_ONLY) + private Long environmentId; + @JsonProperty(access = Access.READ_ONLY) + private String environmentName; + +} + diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataArchiveAttributes.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataArchiveAttributes.java new file mode 100644 index 0000000000..504bd4d92a --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataArchiveAttributes.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import com.oceanbase.odc.service.connection.database.model.Database; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/19 17:03 + * @Descripition: + */ + +@Data +public class DataArchiveAttributes implements ScheduleListAttributes { + + private Database sourceDataBaseInfo; + + private Database targetDataBaseInfo; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataDeleteAttributes.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataDeleteAttributes.java new file mode 100644 index 0000000000..79ca79c6ac --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/DataDeleteAttributes.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import java.util.List; + +import com.oceanbase.odc.service.connection.database.model.Database; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/19 17:02 + * @Descripition: + */ + +@Data +public class DataDeleteAttributes implements ScheduleListAttributes { + + private Database sourceDataBaseInfo; + + private List tableNames; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/JobType.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/JobType.java index 4e36665f92..847148b2d0 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/JobType.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/JobType.java @@ -20,6 +20,7 @@ * @Date: 2022/11/18 17:18 * @Descripition: */ +@Deprecated public enum JobType { SQL_PLAN, diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/OperationType.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/OperationType.java similarity index 85% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/OperationType.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/OperationType.java index d768b01fab..eac16951bb 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/OperationType.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/OperationType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.oceanbase.odc.service.schedule.flowtask; +package com.oceanbase.odc.service.schedule.model; /** * @Author:tinker @@ -26,7 +26,8 @@ public enum OperationType { UPDATE, PAUSE, - TERMINATION, - RESUME + TERMINATE, + RESUME, + DELETE } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java new file mode 100644 index 0000000000..42d72f54b1 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import org.quartz.JobDataMap; + +import com.oceanbase.odc.service.quartz.model.MisfireStrategy; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/9 22:19 + * @Descripition: + */ + +@Data +public class QuartzJobChangeReq { + + private String jobName; + + private String jobGroup; + + private Boolean allowConcurrent = false; + + private MisfireStrategy misfireStrategy = MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING; + + private TriggerConfig triggerConfig = null; + + // To store task parameters. + private JobDataMap jobDataMap = new JobDataMap(); + + private OperationType operationType; +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java index 865dc759be..ae85d7f564 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java @@ -18,6 +18,8 @@ import org.quartz.JobKey; import org.quartz.TriggerKey; +import com.oceanbase.odc.metadb.schedule.ScheduleEntity; + /** * @author yaobin * @date 2023-06-13 @@ -26,6 +28,14 @@ */ public class QuartzKeyGenerator { + public static TriggerKey generateTriggerKey(ScheduleEntity schedule) { + return new TriggerKey(schedule.getId().toString(), schedule.getScheduleType().name()); + } + + public static JobKey generateJobKey(ScheduleEntity schedule) { + return new JobKey(schedule.getId().toString(), schedule.getScheduleType().name()); + } + public static TriggerKey generateTriggerKey(Long scheduleId, JobType jobType) { return new TriggerKey(scheduleId + "", jobType.name()); } @@ -34,12 +44,12 @@ public static JobKey generateJobKey(Long scheduleId, JobType jobType) { return new JobKey(scheduleId + "", jobType.name()); } - public static TriggerKey generateTriggerKey(Long jobId) { - return new TriggerKey(jobId + ""); + public static TriggerKey generateTriggerKey(String name, String group) { + return new TriggerKey(name, group); } - public static JobKey generateJobKey(Long jobId) { - return new JobKey(jobId + ""); + public static JobKey generateJobKey(String jobName, String jobGroup) { + return new JobKey(jobName, jobGroup); } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QueryScheduleParams.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QueryScheduleParams.java index 8565d32cbb..ab35a028c0 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QueryScheduleParams.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QueryScheduleParams.java @@ -35,7 +35,10 @@ public class QueryScheduleParams { private List connectionIds; private Long id; private List statuses; - private JobType type; + private String databaseName; + private String clusterId; + private String tenantId; + private ScheduleType type; private Date startTime; private Date endTime; private String creator; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/Schedule.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/Schedule.java new file mode 100644 index 0000000000..4ba0f8f971 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/Schedule.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import java.util.Date; + +import com.oceanbase.odc.service.quartz.model.MisfireStrategy; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/8 17:40 + * @Descripition: + */ + +@Data +public class Schedule { + + private Long id; + + private Long connectionId; + + private Long databaseId; + + private String databaseName; + + private Long organizationId; + + private Long projectId; + + private ScheduleStatus status; + + private Boolean allowConcurrent = false; + + private MisfireStrategy misfireStrategy = MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING; + + private ScheduleType scheduleType; + + private String parameters; + + private String triggerConfigJson; + + private Long creatorId; + + private String description; + + private Date createTime; + + private Date updateTime; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java new file mode 100644 index 0000000000..57066dba84 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import java.util.Date; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/8 13:24 + * @Descripition: + */ + +@Data +public class ScheduleChangeLog { + + private Long id; + + private Long scheduleId; + + private Long flowInstanceId; + + private OperationType type; + + private String oldScheduleParameterJson; + + private String newScheduleParameterJson; + + private ScheduleChangeStatus status; + + private Date createTime; + + private Date updateTime; + + public static ScheduleChangeLog build(Long scheduleId, OperationType type, String oldParameters, + String newParameters) { + + return build(scheduleId, type, oldParameters, newParameters, null); + } + + public static ScheduleChangeLog build(Long scheduleId, OperationType type, String oldParameters, + String newParameters, Long flowInstanceId) { + ScheduleChangeLog log = new ScheduleChangeLog(); + log.setScheduleId(scheduleId); + log.setStatus(ScheduleChangeStatus.PREPARING); + log.setType(type); + log.setOldScheduleParameterJson(oldParameters); + log.setNewScheduleParameterJson(newParameters); + log.setFlowInstanceId(flowInstanceId); + return log; + } +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLogMapper.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLogMapper.java new file mode 100644 index 0000000000..2917b92bcf --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLogMapper.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.oceanbase.odc.metadb.schedule.ScheduleChangeLogEntity; + +/** + * @Author:tinker + * @Date: 2024/6/8 15:31 + * @Descripition: + */ + +@Mapper +public interface ScheduleChangeLogMapper { + + + ScheduleChangeLogMapper INSTANCE = Mappers.getMapper(ScheduleChangeLogMapper.class); + + ScheduleChangeLog entityToModel(ScheduleChangeLogEntity entity); + + ScheduleChangeLogEntity modelToEntity(ScheduleChangeLog model); + + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java new file mode 100644 index 0000000000..222c6ba3aa --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/25 19:34 + * @Descripition: + */ + +@Data +public class ScheduleChangeReq { + + private Long scheduleId; + + private OperationType operationType; + + private CreateScheduleReq createScheduleReq; + + private UpdateScheduleReq updateScheduleReq; + + public static ScheduleChangeReq with(Long id, OperationType type) { + ScheduleChangeReq req = new ScheduleChangeReq(); + req.setScheduleId(id); + req.setOperationType(type); + return req; + } + + public static ScheduleChangeReq with(CreateScheduleReq createScheduleReq) { + ScheduleChangeReq req = new ScheduleChangeReq(); + req.setOperationType(OperationType.CREATE); + req.setCreateScheduleReq(createScheduleReq); + return req; + } + + public static ScheduleChangeReq with(Long id, UpdateScheduleReq updateScheduleReq) { + ScheduleChangeReq req = new ScheduleChangeReq(); + req.setScheduleId(id); + req.setOperationType(OperationType.UPDATE); + req.setUpdateScheduleReq(updateScheduleReq); + return req; + } + + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeStatus.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeStatus.java new file mode 100644 index 0000000000..c3523797bc --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeStatus.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +/** + * @Author:tinker + * @Date: 2024/6/8 15:23 + * @Descripition: + */ +public enum ScheduleChangeStatus { + + PREPARING, + APPROVING, + CHANGING, + SUCCESS, + FAILED + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java index d3bbfae4f9..587cf89e29 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,35 +17,13 @@ import java.util.Date; import java.util.List; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.commons.collections4.CollectionUtils; import com.fasterxml.jackson.annotation.JsonRawValue; import com.oceanbase.odc.common.i18n.Internationalizable; -import com.oceanbase.odc.common.json.JsonUtils; -import com.oceanbase.odc.core.shared.OrganizationIsolated; -import com.oceanbase.odc.core.shared.constant.DialectType; -import com.oceanbase.odc.core.shared.constant.ResourceType; -import com.oceanbase.odc.metadb.flow.FlowInstanceEntity; -import com.oceanbase.odc.metadb.iam.UserEntity; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.service.common.model.InnerUser; -import com.oceanbase.odc.service.connection.database.model.Database; -import com.oceanbase.odc.service.connection.model.ConnectionConfig; -import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; -import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; -import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; -import com.oceanbase.odc.service.quartz.util.QuartzCronExpressionUtils; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NonNull; -import lombok.ToString; /** * @Author:tinker @@ -54,173 +32,34 @@ */ @Data -public class ScheduleDetailResp implements OrganizationIsolated { +public class ScheduleDetailResp { + + private Long scheduleId; + + private ScheduleType type; - private Long id; - private Long organizationId; - private JobType type; - private Database database; private Long projectId; + private InnerUser creator; + private Date createTime; + private Date updateTime; + private ScheduleStatus status; + @Internationalizable private String description; - private boolean approvable; - private Long approveInstanceId; + private Boolean allowConcurrent; + private MisfireStrategy misfireStrategy; - private Set candidateApprovers; private List nextFireTimes; - private List jobs; @JsonRawValue - private String jobParameters; + private String parameters; @JsonRawValue private String triggerConfig; - public static ScheduleDetailResp withId(@NonNull Long id) { - ScheduleDetailResp resp = new ScheduleDetailResp(); - resp.setId(id); - return resp; - } - - @Override - public String resourceType() { - return ResourceType.ODC_SCHEDULE.name(); - } - - @Override - public Long organizationId() { - return this.organizationId; - } - - @Override - public Long id() { - return this.id; - } - - @Getter - @ToString - @EqualsAndHashCode - public static class InnerConnection { - private final Long id; - private final String name; - private final DialectType dbMode; - - public InnerConnection(@NonNull ConnectionConfig config) { - this.id = config.getId(); - this.name = config.getName(); - this.dbMode = config.getDialectType(); - } - } - - public static class ScheduleResponseMapper { - - private Function getUserById = null; - private Function getApproveInstanceIdById = null; - - private Function getDatabaseById = null; - - private Function> getCandidatesById = null; - - private Function getDLMRateLimitConfigurationById = null; - - - public ScheduleResponseMapper withGetUserById(@NonNull Function getUserById) { - this.getUserById = getUserById; - return this; - } - - public ScheduleResponseMapper withGetApproveInstanceIdById( - @NonNull Function getApproveInstanceIdById) { - this.getApproveInstanceIdById = getApproveInstanceIdById; - return this; - } - - public ScheduleResponseMapper withGetDatabaseById( - @NonNull Function getDatabaseById) { - this.getDatabaseById = getDatabaseById; - return this; - } - - public ScheduleResponseMapper withGetCandidatesById( - @NonNull Function> getCandidatesById) { - this.getCandidatesById = getCandidatesById; - return this; - } - - public ScheduleResponseMapper withGetDLMRateLimitConfigurationById( - @NonNull Function getCandidatesById) { - this.getDLMRateLimitConfigurationById = getCandidatesById; - return this; - } - - - public ScheduleDetailResp map(@NonNull ScheduleEntity entity) { - - ScheduleDetailResp resp = new ScheduleDetailResp(); - resp.setId(entity.getId()); - resp.setType(entity.getJobType()); - resp.setStatus(entity.getStatus()); - - resp.setOrganizationId(entity.getOrganizationId()); - resp.setProjectId(entity.getProjectId()); - resp.setDatabase(getDatabaseById.apply(entity.getDatabaseId())); - resp.setJobParameters(getJobParameters(entity)); - resp.setTriggerConfig(entity.getTriggerConfigJson()); - resp.setNextFireTimes( - QuartzCronExpressionUtils.getNextFiveFireTimes(JsonUtils.fromJson(entity.getTriggerConfigJson(), - TriggerConfig.class).getCronExpression())); - UserEntity user = getUserById.apply(entity.getCreatorId()); - if (user != null) { - resp.setCreator(new InnerUser(user)); - } - resp.setCreateTime(entity.getCreateTime()); - resp.setUpdateTime(entity.getUpdateTime()); - resp.setDescription(entity.getDescription()); - - Long approveInstanceId = getApproveInstanceIdById.apply(entity.getId()); - resp.setApprovable(approveInstanceId != null); - resp.setApproveInstanceId(approveInstanceId); - - resp.setMisfireStrategy(entity.getMisfireStrategy()); - resp.setAllowConcurrent(entity.getAllowConcurrent()); - Set candidates = getCandidatesById.apply(entity.getId()); - if (CollectionUtils.isNotEmpty(candidates)) { - resp.setCandidateApprovers(candidates.stream().map(InnerUser::new).collect(Collectors.toSet())); - } - - return resp; - } - - private String getJobParameters(ScheduleEntity entity) { - RateLimitConfiguration rateLimitConfig = getDLMRateLimitConfigurationById.apply(entity.getId()); - if (rateLimitConfig == null) { - return entity.getJobParametersJson(); - } - switch (entity.getJobType()) { - case DATA_ARCHIVE: { - DataArchiveParameters parameters = - JsonUtils.fromJson(entity.getJobParametersJson(), DataArchiveParameters.class); - parameters.setRateLimit(rateLimitConfig); - return JsonUtils.toJson(parameters); - } - case DATA_DELETE: { - DataDeleteParameters parameters = - JsonUtils.fromJson(entity.getJobParametersJson(), DataDeleteParameters.class); - parameters.setRateLimit(rateLimitConfig); - return JsonUtils.toJson(parameters); - - } - default: { - return entity.getJobParametersJson(); - } - } - - } - - } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java new file mode 100644 index 0000000000..1355f2ddc4 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +/** + * @Author:tinker + * @Date: 2024/6/10 17:28 + * @Descripition: + */ +public interface ScheduleListAttributes { + + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java new file mode 100644 index 0000000000..27a918d5d9 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import java.util.Date; + +import com.oceanbase.odc.core.shared.constant.TaskStatus; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/8 13:30 + * @Descripition: + */ + + + +@Data +public class ScheduleListResp { + + private Long scheduleId; + + private ScheduleListAttributes attributes; + + private ScheduleStatus status; + + private Date latestFireTime; + + private TaskStatus latestExecutionStatus; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java new file mode 100644 index 0000000000..07044bece9 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.oceanbase.odc.service.schedule.model; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.oceanbase.odc.metadb.schedule.ScheduleEntity; + +/** + * @Author:tinker + * @Date: 2023/6/6 20:13 + * @Descripition: + */ + +@Mapper +public interface ScheduleMapper { + + ScheduleMapper INSTANCE = Mappers.getMapper(ScheduleMapper.class); + + Schedule entityToModel(ScheduleEntity entity); + + ScheduleEntity modelToEntity(Schedule model); +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleStatus.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleStatus.java index 2507fb8585..30808b0cd0 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleStatus.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleStatus.java @@ -21,6 +21,8 @@ * @Descripition: */ public enum ScheduleStatus { + + CREATING, APPROVING, APPROVAL_EXPIRED, @@ -28,9 +30,9 @@ public enum ScheduleStatus { REJECTED, PAUSE, ENABLED, - TERMINATION, + TERMINATED, COMPLETED, - EXECUTION_FAILED; + EXECUTION_FAILED } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTask.java similarity index 76% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskResp.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTask.java index 38c8d13499..9815b9b82d 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskResp.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.oceanbase.odc.service.schedule.model; import java.util.Date; @@ -20,16 +21,15 @@ import com.oceanbase.odc.core.shared.constant.TaskStatus; import lombok.Data; -import lombok.NonNull; /** * @Author:tinker - * @Date: 2023/5/24 15:35 + * @Date: 2024/6/18 10:55 * @Descripition: */ @Data -public class ScheduleTaskResp { +public class ScheduleTask { private Long id; @@ -37,22 +37,22 @@ public class ScheduleTaskResp { private String jobGroup; + private String parametersJson; + private TaskStatus status; - private double progressPercentage; + private Date fireTime; - private String executionDetails; + private double progressPercentage; private String resultJson; + private String executor; + private Date createTime; private Date updateTime; - public static ScheduleTaskResp withId(@NonNull Long id) { - ScheduleTaskResp resp = new ScheduleTaskResp(); - resp.setId(id); - return resp; - } + private Long jobId; } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskDetailResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskDetailResp.java new file mode 100644 index 0000000000..347aeabc15 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskDetailResp.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import java.util.Date; + +import com.oceanbase.odc.core.shared.constant.TaskStatus; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/25 15:20 + * @Descripition: + */ + +@Data +public class ScheduleTaskDetailResp { + + private Long id; + + private ScheduleTaskType type; + + private TaskStatus status; + + private String parameters; + + private String executionDetails; + + private Date fireTime; + + private Date createTime; + + private Date updateTime; +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java new file mode 100644 index 0000000000..6256c14026 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +import java.util.Date; + +import com.oceanbase.odc.core.shared.constant.TaskStatus; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/6/19 14:31 + * @Descripition: + */ + + +@Data +public class ScheduleTaskListResp { + + private Long id; + + private ScheduleTaskType type; + + private TaskStatus status; + + private Date createTime; + + private Date updateTime; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java new file mode 100644 index 0000000000..6ae727abbd --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +/** + * @Author:tinker + * @Date: 2024/6/19 15:35 + * @Descripition: + */ +public class ScheduleTaskListRespMapper { + + public static ScheduleTaskListResp map(ScheduleTask scheduleTask) { + ScheduleTaskListResp t = new ScheduleTaskListResp(); + t.setId(scheduleTask.getId()); + t.setStatus(scheduleTask.getStatus()); + t.setType(ScheduleTaskType.valueOf(scheduleTask.getJobGroup())); + t.setCreateTime(scheduleTask.getCreateTime()); + t.setUpdateTime(scheduleTask.getUpdateTime()); + return t; + } + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskMapper.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskMapper.java index 63de787269..38e48b1cbd 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskMapper.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskMapper.java @@ -31,7 +31,7 @@ public interface ScheduleTaskMapper { ScheduleTaskMapper INSTANCE = Mappers.getMapper(ScheduleTaskMapper.class); - ScheduleTaskResp entityToModel(ScheduleTaskEntity entity); + ScheduleTask entityToModel(ScheduleTaskEntity entity); - ScheduleTaskEntity modelToEntity(ScheduleTaskResp model); + ScheduleTaskEntity modelToEntity(ScheduleTask model); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskParameters.java new file mode 100644 index 0000000000..18c6c3999a --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskParameters.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +/** + * @Author:tinker + * @Date: 2024/6/8 15:57 + * @Descripition: + */ +public interface ScheduleTaskParameters { +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskType.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskType.java new file mode 100644 index 0000000000..2ba39c1dc0 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskType.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.model; + +/** + * @Author:tinker + * @Date: 2024/6/18 16:56 + * @Descripition: + */ +public enum ScheduleTaskType { + + SQL_PLAN, + + PARTITION_PLAN, + + DATA_ARCHIVE, + + DATA_ARCHIVE_DELETE, + + DATA_DELETE, + + DATA_ARCHIVE_ROLLBACK, + + ONLINE_SCHEMA_CHANGE_COMPLETE + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleType.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleType.java new file mode 100644 index 0000000000..8fc92a6e9f --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleType.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.oceanbase.odc.service.schedule.model; + +/** + * @Author:tinker + * @Date: 2022/11/18 17:18 + * @Descripition: + */ +public enum ScheduleType { + + SQL_PLAN, + + PARTITION_PLAN, + + DATA_ARCHIVE, + + DATA_DELETE, + + ONLINE_SCHEMA_CHANGE_COMPLETE; + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/TriggerConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/TriggerConfig.java index e969c14bb4..504cbac9b1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/TriggerConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/TriggerConfig.java @@ -55,7 +55,4 @@ public String getCronExpression() { } } - public boolean isSingleTrigger() { - return triggerStrategy == TriggerStrategy.START_AT || triggerStrategy == TriggerStrategy.START_NOW; - } } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/UpdateScheduleReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/UpdateScheduleReq.java new file mode 100644 index 0000000000..4106c8484d --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/UpdateScheduleReq.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.oceanbase.odc.service.schedule.model; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; +import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; + +import lombok.Data; + +/** + * @Author:tinker + * @Date: 2024/5/27 18:42 + * @Descripition: + */ + + +@Data +public class UpdateScheduleReq { + + + @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "type") + @JsonSubTypes(value = { + @JsonSubTypes.Type(value = DataArchiveParameters.class, name = "DATA_ARCHIVE"), + @JsonSubTypes.Type(value = DataDeleteParameters.class, name = "DATA_DELETE") + }) + private ScheduleTaskParameters parameters; + + // DATA_ARCHIVE、DATA_DELETE、PARTITION_PLAN + private ScheduleType type; + + private TriggerConfig triggerConfig; + + private String description; + +} + diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AbstractDlmJobPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java similarity index 80% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AbstractDlmJobPreprocessor.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java index 465ed2d4aa..7ac874e34a 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/AbstractDlmJobPreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.oceanbase.odc.service.schedule.flowtask; +package com.oceanbase.odc.service.schedule.processor; import java.util.Date; import java.util.HashMap; @@ -21,23 +21,19 @@ import java.util.List; import java.util.Map; -import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.common.util.StringUtils; import com.oceanbase.odc.core.session.ConnectionSession; import com.oceanbase.odc.core.session.ConnectionSessionConstants; import com.oceanbase.odc.core.shared.constant.DialectType; import com.oceanbase.odc.core.shared.exception.UnsupportedException; import com.oceanbase.odc.core.sql.execute.SyncJdbcExecutor; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.dlm.DlmLimiterService; import com.oceanbase.odc.service.dlm.model.DataArchiveTableConfig; import com.oceanbase.odc.service.dlm.model.OffsetConfig; import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; import com.oceanbase.odc.service.dlm.utils.DataArchiveConditionUtil; -import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; -import com.oceanbase.odc.service.flow.processor.Preprocessor; -import com.oceanbase.odc.service.schedule.model.ScheduleStatus; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; import com.oceanbase.tools.dbbrowser.util.MySQLSqlBuilder; import com.oceanbase.tools.dbbrowser.util.OracleSqlBuilder; import com.oceanbase.tools.dbbrowser.util.SqlBuilder; @@ -51,28 +47,10 @@ */ @Slf4j -public class AbstractDlmJobPreprocessor implements Preprocessor { +public class AbstractDlmPreprocessor implements Preprocessor { @Override - public void process(CreateFlowInstanceReq req) {} - - public ScheduleEntity buildScheduleEntity(CreateFlowInstanceReq req) { - AlterScheduleParameters parameters = (AlterScheduleParameters) req.getParameters(); - ScheduleEntity scheduleEntity = new ScheduleEntity(); - scheduleEntity.setConnectionId(req.getConnectionId()); - scheduleEntity.setDatabaseName(req.getDatabaseName()); - scheduleEntity.setDatabaseId(req.getDatabaseId()); - scheduleEntity.setProjectId(req.getProjectId()); - scheduleEntity.setJobType(parameters.getType()); - scheduleEntity.setStatus(ScheduleStatus.APPROVING); - scheduleEntity.setAllowConcurrent(parameters.getAllowConcurrent()); - scheduleEntity.setMisfireStrategy(parameters.getMisfireStrategy()); - scheduleEntity.setJobParametersJson(JsonUtils.toJson(parameters.getScheduleTaskParameters())); - scheduleEntity.setTriggerConfigJson(JsonUtils.toJson(parameters.getTriggerConfig())); - scheduleEntity.setModifierId(scheduleEntity.getCreatorId()); - scheduleEntity.setDescription(req.getDescription()); - return scheduleEntity; - } + public void process(ScheduleChangeReq req) {} public void checkTableAndCondition(ConnectionSession connectionSession, Database sourceDb, List tables, diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java new file mode 100644 index 0000000000..26a8a80b65 --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.schedule.processor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; + +import com.oceanbase.odc.core.shared.exception.UnsupportedException; +import com.oceanbase.odc.service.collaboration.project.ProjectService; +import com.oceanbase.odc.service.connection.database.DatabaseService; +import com.oceanbase.odc.service.connection.database.model.Database; +import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; +import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; +import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; +import com.oceanbase.odc.service.schedule.ScheduleService; +import com.oceanbase.odc.service.schedule.model.CreateScheduleReq; +import com.oceanbase.odc.service.schedule.model.OperationType; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleType; + +/** + * @Author:tinker + * @Date: 2024/6/25 17:01 + * @Descripition: + */ +public class CreateScheduleAspect implements InitializingBean { + @Autowired + private DatabaseService databaseService; + @Autowired + private AuthenticationFacade authenticationFacade; + @Autowired + private ScheduleService scheduleService; + @Autowired + private List preprocessors; + @Autowired + private ProjectService projectService; + + private final Map type2Processor = new HashMap<>(); + + + @Pointcut("@annotation(com.oceanbase.odc.service.flow.processor.EnablePreprocess) && args(com.oceanbase.odc.service.schedule.model.ScheduleChangeReq)") + public void processBeforeChangeSchedule() {} + + + @Before("processBeforeChangeSchedule()") + public void createPreprocess(JoinPoint point) throws Throwable { + ScheduleChangeReq req = (ScheduleChangeReq) point.getArgs()[0]; + + ScheduleType type; + if (req.getOperationType() == OperationType.CREATE) { + type = req.getCreateScheduleReq().getType(); + adaptCreateScheduleReq(req.getCreateScheduleReq()); + } else { + type = scheduleService.nullSafeGetModelById(req.getScheduleId()).getScheduleType(); + } + if (type2Processor.containsKey(type)) { + type2Processor.get(type).process(req); + } + } + + @Override + public void afterPropertiesSet() throws Exception { + preprocessors.forEach(preprocessor -> { + // Init schedule task processor. + if (preprocessor.getClass().isAnnotationPresent(ScheduleTaskPreprocessor.class)) { + ScheduleTaskPreprocessor annotation = + preprocessor.getClass().getAnnotation(ScheduleTaskPreprocessor.class); + if (annotation.isEnabled()) { + if (type2Processor.containsKey(annotation.type())) { + throw new RuntimeException( + String.format("The processor has already been defined,type=%s", annotation.type())); + } + type2Processor.put(annotation.type(), preprocessor); + } + } + }); + } + + private void adaptCreateScheduleReq(CreateScheduleReq req) { + Database srcDb = databaseService.detail(getTargetDatabaseId(req)); + req.setProjectId(srcDb.getProject().getId()); + req.setProjectName(srcDb.getProject().getName()); + req.setConnectionId(srcDb.getDataSource().getId()); + req.setConnectionName(srcDb.getDataSource().getName()); + req.setEnvironmentId(srcDb.getEnvironment().getId()); + req.setEnvironmentName(srcDb.getEnvironment().getName()); + req.setDatabaseName(srcDb.getName()); + req.setDatabaseId(req.getDatabaseId()); + } + + private Long getTargetDatabaseId(CreateScheduleReq req) { + switch (req.getType()) { + case DATA_ARCHIVE: { + DataArchiveParameters parameters = (DataArchiveParameters) req.getParameters(); + return parameters.getSourceDatabaseId(); + } + case DATA_DELETE: { + DataDeleteParameters parameters = (DataDeleteParameters) req.getParameters(); + return parameters.getDatabaseId(); + } + default: + throw new UnsupportedException(); + } + } + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/DataArchivePreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java similarity index 60% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/DataArchivePreprocessor.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java index 81194f622b..7071a8f5f1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/DataArchivePreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.oceanbase.odc.service.schedule.flowtask; - -import java.util.Arrays; -import java.util.List; +package com.oceanbase.odc.service.schedule.processor; import org.springframework.beans.factory.annotation.Autowired; @@ -25,10 +22,7 @@ import com.oceanbase.odc.core.session.ConnectionSessionConstants; import com.oceanbase.odc.core.session.ConnectionSessionFactory; import com.oceanbase.odc.core.shared.constant.DialectType; -import com.oceanbase.odc.core.shared.constant.TaskStatus; import com.oceanbase.odc.core.shared.exception.UnsupportedException; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; -import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.plugin.connect.api.InformationExtensionPoint; import com.oceanbase.odc.service.connection.database.DatabaseService; import com.oceanbase.odc.service.connection.database.model.Database; @@ -36,14 +30,11 @@ import com.oceanbase.odc.service.dlm.DLMConfiguration; import com.oceanbase.odc.service.dlm.DlmLimiterService; import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; -import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; -import com.oceanbase.odc.service.flow.processor.ScheduleTaskPreprocessor; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; import com.oceanbase.odc.service.plugin.ConnectionPluginUtil; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.ScheduleTaskService; -import com.oceanbase.odc.service.schedule.model.JobType; -import com.oceanbase.odc.service.schedule.model.ScheduleStatus; +import com.oceanbase.odc.service.schedule.model.OperationType; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.session.factory.DefaultConnectSessionFactory; import lombok.extern.slf4j.Slf4j; @@ -54,17 +45,11 @@ * @Descripition: */ @Slf4j -@ScheduleTaskPreprocessor(type = JobType.DATA_ARCHIVE) -public class DataArchivePreprocessor extends AbstractDlmJobPreprocessor { +@ScheduleTaskPreprocessor(type = ScheduleType.DATA_ARCHIVE) +public class DataArchivePreprocessor extends AbstractDlmPreprocessor { @Autowired private AuthenticationFacade authenticationFacade; - @Autowired - private ScheduleService scheduleService; - - @Autowired - private ScheduleTaskService scheduleTaskService; - @Autowired private DatabaseService databaseService; @@ -75,26 +60,22 @@ public class DataArchivePreprocessor extends AbstractDlmJobPreprocessor { private DLMConfiguration dlmConfiguration; @Override - public void process(CreateFlowInstanceReq req) { - AlterScheduleParameters parameters = (AlterScheduleParameters) req.getParameters(); - if (parameters.getOperationType() == OperationType.CREATE - || parameters.getOperationType() == OperationType.UPDATE) { - DataArchiveParameters dataArchiveParameters = - (DataArchiveParameters) parameters.getScheduleTaskParameters(); - initDefaultConfig(dataArchiveParameters); + public void process(ScheduleChangeReq req) { + if (req.getOperationType() == OperationType.CREATE || req.getOperationType() == OperationType.UPDATE) { + DataArchiveParameters parameters = req.getOperationType() == OperationType.CREATE + ? (DataArchiveParameters) req.getCreateScheduleReq().getParameters() + : (DataArchiveParameters) req.getUpdateScheduleReq().getParameters(); + + initDefaultConfig(parameters); // Throw exception when the specified database does not exist or the current user does not have // permission to access it. - Database sourceDb = databaseService.detail(dataArchiveParameters.getSourceDatabaseId()); - Database targetDb = databaseService.detail(dataArchiveParameters.getTargetDataBaseId()); - if (!dataArchiveParameters.getSyncTableStructure().isEmpty() + Database sourceDb = databaseService.detail(parameters.getSourceDatabaseId()); + Database targetDb = databaseService.detail(parameters.getTargetDataBaseId()); + if (!parameters.getSyncTableStructure().isEmpty() && sourceDb.getDataSource().getDialectType() != targetDb.getDataSource().getDialectType()) { throw new UnsupportedException( "Different types of databases do not support structural synchronization."); } - dataArchiveParameters.setSourceDatabaseName(sourceDb.getName()); - dataArchiveParameters.setTargetDatabaseName(targetDb.getName()); - dataArchiveParameters.setSourceDataSourceName(sourceDb.getDataSource().getName()); - dataArchiveParameters.setTargetDataSourceName(targetDb.getDataSource().getName()); ConnectionConfig sourceDs = sourceDb.getDataSource(); sourceDs.setDefaultSchema(sourceDb.getName()); ConnectionSessionFactory sourceSessionFactory = new DefaultConnectSessionFactory(sourceDs); @@ -103,41 +84,14 @@ public void process(CreateFlowInstanceReq req) { ConnectionSession targetSession = targetSessionFactory.generateSession(); try { supportDataArchivingLink(sourceSession, targetSession); - checkTableAndCondition(sourceSession, sourceDb, dataArchiveParameters.getTables(), - dataArchiveParameters.getVariables()); + checkTableAndCondition(sourceSession, sourceDb, parameters.getTables(), + parameters.getVariables()); } finally { sourceSession.expire(); targetSession.expire(); } - if (parameters.getOperationType() == OperationType.CREATE) { - // pre create - ScheduleEntity scheduleEntity = buildScheduleEntity(req); - scheduleEntity.setCreatorId(authenticationFacade.currentUser().id()); - scheduleEntity.setModifierId(scheduleEntity.getCreatorId()); - scheduleEntity.setOrganizationId(authenticationFacade.currentOrganizationId()); - scheduleEntity = scheduleService.create(scheduleEntity); - parameters.setTaskId(scheduleEntity.getId()); - // create job limit config - initLimiterConfig(scheduleEntity.getId(), dataArchiveParameters.getRateLimit(), limiterService); - } - if (parameters.getOperationType() == OperationType.UPDATE) { - parameters.setDescription(req.getDescription()); - ScheduleEntity scheduleEntity = scheduleService.nullSafeGetById(parameters.getTaskId()); - List runningTasks = scheduleTaskService.listTaskByJobNameAndStatus( - scheduleEntity.getId().toString(), Arrays.asList(TaskStatus.RUNNING, TaskStatus.PREPARING)); - if (scheduleEntity.getStatus() != ScheduleStatus.PAUSE || !runningTasks.isEmpty()) { - throw new IllegalStateException( - String.format( - "The task can only be edited when it is paused and there are no active subtasks executing." - + "status=%s,subtaskCount=%s", - scheduleEntity.getStatus(), runningTasks.size())); - } - // update job limit config - limiterService.updateByOrderId(scheduleEntity.getId(), dataArchiveParameters.getRateLimit()); - } log.info("Data archive preprocessing has been completed."); } - req.setParentFlowInstanceId(parameters.getTaskId()); } private void supportDataArchivingLink(ConnectionSession sourceSession, ConnectionSession targetSession) { diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/DataDeletePreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java similarity index 57% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/DataDeletePreprocessor.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java index d48cf1a00c..e43e7898a4 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/flowtask/DataDeletePreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.oceanbase.odc.service.schedule.flowtask; +package com.oceanbase.odc.service.schedule.processor; import java.util.Objects; @@ -21,18 +21,16 @@ import com.oceanbase.odc.core.session.ConnectionSession; import com.oceanbase.odc.core.session.ConnectionSessionFactory; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.service.connection.database.DatabaseService; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.connection.model.ConnectionConfig; import com.oceanbase.odc.service.dlm.DLMConfiguration; import com.oceanbase.odc.service.dlm.DlmLimiterService; import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; -import com.oceanbase.odc.service.flow.model.CreateFlowInstanceReq; -import com.oceanbase.odc.service.flow.processor.ScheduleTaskPreprocessor; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; -import com.oceanbase.odc.service.schedule.ScheduleService; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.OperationType; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.session.factory.DefaultConnectSessionFactory; import lombok.extern.slf4j.Slf4j; @@ -43,15 +41,12 @@ * @Descripition: */ @Slf4j -@ScheduleTaskPreprocessor(type = JobType.DATA_DELETE) -public class DataDeletePreprocessor extends AbstractDlmJobPreprocessor { +@ScheduleTaskPreprocessor(type = ScheduleType.DATA_DELETE) +public class DataDeletePreprocessor extends AbstractDlmPreprocessor { @Autowired private AuthenticationFacade authenticationFacade; - @Autowired - private ScheduleService scheduleService; - @Autowired private DatabaseService databaseService; @@ -62,47 +57,34 @@ public class DataDeletePreprocessor extends AbstractDlmJobPreprocessor { private DLMConfiguration dlmConfiguration; @Override - public void process(CreateFlowInstanceReq req) { - AlterScheduleParameters parameters = (AlterScheduleParameters) req.getParameters(); - if (parameters.getOperationType() == OperationType.CREATE) { - DataDeleteParameters dataDeleteParameters = - (DataDeleteParameters) parameters.getScheduleTaskParameters(); - initDefaultConfig(dataDeleteParameters); + public void process(ScheduleChangeReq req) { + if (req.getOperationType() == OperationType.CREATE || req.getOperationType() == OperationType.UPDATE) { + DataDeleteParameters parameters = req.getOperationType() == OperationType.CREATE + ? (DataDeleteParameters) req.getCreateScheduleReq().getParameters() + : (DataDeleteParameters) req.getUpdateScheduleReq().getParameters(); + initDefaultConfig(parameters); // Throw exception when the specified database does not exist or the current user does not have // permission to access it. // if check before delete, need verify target database. - if (dataDeleteParameters.getNeedCheckBeforeDelete()) { - if (Objects.isNull(dataDeleteParameters.getTargetDatabaseId())) { + if (parameters.getNeedCheckBeforeDelete()) { + if (Objects.isNull(parameters.getTargetDatabaseId())) { throw new IllegalArgumentException("target database id can not be null"); } - Database targetDb = databaseService.detail(dataDeleteParameters.getTargetDatabaseId()); - dataDeleteParameters.setTargetDatabaseName(targetDb.getName()); - dataDeleteParameters.setTargetDataSourceName(targetDb.getDataSource().getName()); + Database targetDb = databaseService.detail(parameters.getTargetDatabaseId()); } - Database sourceDb = databaseService.detail(dataDeleteParameters.getDatabaseId()); - dataDeleteParameters.setDatabaseName(sourceDb.getName()); - dataDeleteParameters.setSourceDataSourceName(sourceDb.getDataSource().getName()); + Database sourceDb = databaseService.detail(parameters.getDatabaseId()); ConnectionConfig dataSource = sourceDb.getDataSource(); dataSource.setDefaultSchema(sourceDb.getName()); ConnectionSessionFactory connectionSessionFactory = new DefaultConnectSessionFactory(dataSource); ConnectionSession connectionSession = connectionSessionFactory.generateSession(); try { - checkTableAndCondition(connectionSession, sourceDb, dataDeleteParameters.getTables(), - dataDeleteParameters.getVariables()); + checkTableAndCondition(connectionSession, sourceDb, parameters.getTables(), + parameters.getVariables()); } finally { connectionSession.expire(); } log.info("QUICK-DELETE job preprocessing has been completed."); - // pre create - ScheduleEntity scheduleEntity = buildScheduleEntity(req); - scheduleEntity.setCreatorId(authenticationFacade.currentUser().id()); - scheduleEntity.setModifierId(scheduleEntity.getCreatorId()); - scheduleEntity.setOrganizationId(authenticationFacade.currentOrganizationId()); - scheduleEntity = scheduleService.create(scheduleEntity); - parameters.setTaskId(scheduleEntity.getId()); - initLimiterConfig(scheduleEntity.getId(), dataDeleteParameters.getRateLimit(), limiterService); } - req.setParentFlowInstanceId(parameters.getTaskId()); } private void initDefaultConfig(DataDeleteParameters parameters) { diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java new file mode 100644 index 0000000000..302414645e --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.oceanbase.odc.service.schedule.processor; + +import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; + +/** + * @Author:tinker + * @Date: 2024/6/25 10:53 + * @Descripition: + */ +public interface Preprocessor { + + void process(ScheduleChangeReq req); + +} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ScheduleTaskPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java similarity index 85% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ScheduleTaskPreprocessor.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java index 582785e41c..71966287e6 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ScheduleTaskPreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 OceanBase. + * Copyright (c) 2024 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.oceanbase.odc.service.flow.processor; +package com.oceanbase.odc.service.schedule.processor; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -22,7 +22,7 @@ import org.springframework.stereotype.Component; -import com.oceanbase.odc.service.schedule.model.JobType; +import com.oceanbase.odc.service.schedule.model.ScheduleType; /** * @Author:tinker @@ -36,6 +36,6 @@ boolean isEnabled() default true; - JobType type(); + ScheduleType type(); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobProcessUpdateListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobProcessUpdateListener.java index 1d71c0f3f7..844024604c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobProcessUpdateListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobProcessUpdateListener.java @@ -24,12 +24,11 @@ import com.oceanbase.odc.common.event.AbstractEventListener; import com.oceanbase.odc.common.json.JsonUtils; -import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; -import com.oceanbase.odc.metadb.schedule.ScheduleTaskRepository; import com.oceanbase.odc.metadb.task.JobEntity; import com.oceanbase.odc.metadb.task.TaskEntity; import com.oceanbase.odc.service.common.util.UrlUtils; import com.oceanbase.odc.service.schedule.ScheduleTaskService; +import com.oceanbase.odc.service.schedule.model.ScheduleTask; import com.oceanbase.odc.service.task.TaskService; import com.oceanbase.odc.service.task.executor.task.TaskResult; import com.oceanbase.odc.service.task.model.ExecutorInfo; @@ -47,8 +46,6 @@ @Slf4j public class DefaultJobProcessUpdateListener extends AbstractEventListener { - @Autowired - private ScheduleTaskRepository taskRepository; @Autowired private ScheduleTaskService scheduleTaskService; @Autowired @@ -62,7 +59,7 @@ public void onEvent(DefaultJobProcessUpdateEvent event) { JobIdentity identity = taskResult.getJobIdentity(); JobEntity jobEntity = stdTaskFrameworkService.find(identity.getId()); - Optional scheduleTaskEntityOptional = scheduleTaskService.findByJobId(jobEntity.getId()); + Optional scheduleTaskEntityOptional = scheduleTaskService.findByJobId(jobEntity.getId()); if (scheduleTaskEntityOptional.isPresent()) { updateScheduleTask(taskResult, scheduleTaskEntityOptional.get()); return; @@ -71,7 +68,7 @@ public void onEvent(DefaultJobProcessUpdateEvent event) { taskEntityOptional.ifPresent(taskEntity -> updateTask(taskResult, taskEntity)); } - private void updateScheduleTask(TaskResult taskResult, ScheduleTaskEntity taskEntity) { + private void updateScheduleTask(TaskResult taskResult, ScheduleTask taskEntity) { taskEntity.setProgressPercentage(taskResult.getProgress()); taskEntity.setStatus(taskResult.getStatus().convertTaskStatus()); taskEntity.setResultJson(taskResult.getResultJson()); @@ -82,7 +79,7 @@ private void updateScheduleTask(TaskResult taskResult, ScheduleTaskEntity taskEn executorInfo.setPort(uc.getPort()); taskEntity.setExecutor(JsonUtils.toJson(executorInfo)); } - taskRepository.update(taskEntity); + scheduleTaskService.update(taskEntity); log.debug("Update scheduleTask successfully, scheduleTaskId={}.", taskEntity.getId()); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobTerminateListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobTerminateListener.java index 135349e83f..2c45103393 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobTerminateListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/DefaultJobTerminateListener.java @@ -78,7 +78,7 @@ public void onEvent(JobTerminateEvent event) { // Trigger the data-delete job if necessary after the data-archive task is completed. if (parameters.getJobType() == com.oceanbase.tools.migrator.common.enums.JobType.MIGRATE && parameters.isDeleteAfterMigration()) { - scheduleService.dataArchiveDelete(Long.parseLong(o.getJobName()), o.getId()); + scheduleTaskService.triggerDataArchiveDelete(o.getId()); log.info("Trigger delete job succeed."); } }); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/JobTerminateNotifyListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/JobTerminateNotifyListener.java index d7f92e830a..2c1e946d88 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/JobTerminateNotifyListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/task/listener/JobTerminateNotifyListener.java @@ -19,7 +19,6 @@ import org.springframework.stereotype.Component; import com.oceanbase.odc.common.event.AbstractEventListener; -import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.metadb.task.JobEntity; import com.oceanbase.odc.service.notification.Broker; import com.oceanbase.odc.service.notification.NotificationProperties; @@ -61,9 +60,8 @@ public void onEvent(JobTerminateEvent event) { JobEntity jobEntity = taskFrameworkService.find(event.getJi().getId()); scheduleTaskService.findByJobId(jobEntity.getId()) .ifPresent(task -> { - ScheduleEntity schedule = scheduleService.nullSafeGetById(Long.parseLong(task.getJobName())); - broker.enqueueEvent(event.getStatus() == JobStatus.DONE ? eventBuilder.ofSucceededTask(schedule) - : eventBuilder.ofFailedTask(schedule)); + broker.enqueueEvent(event.getStatus() == JobStatus.DONE ? eventBuilder.ofSucceededTask(task) + : eventBuilder.ofFailedTask(task)); }); } catch (Exception e) { log.warn("Failed to enqueue event.", e); From 4996c4ffa71d18fdb895c8f22fe8d3afcc1ad4a0 Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 27 Jun 2024 22:25:30 +0800 Subject: [PATCH 02/18] several bugfix --- .../LatestScheduleTaskLinkRepositoryTest.java | 3 +- .../web/controller/v2/ScheduleController.java | 44 ++++++----- .../LatestScheduleTaskLinkEntity.java | 3 +- .../LatestScheduleTaskLinkRepository.java | 3 +- .../schedule/ScheduleChangeLogEntity.java | 2 +- .../odc/metadb/schedule/ScheduleEntity.java | 2 +- .../metadb/schedule/ScheduleRepository.java | 2 +- .../dlm/DLMTableStructureSynchronizer.java | 4 + .../dlm/model/DataArchiveParameters.java | 1 - .../dlm/model/DataDeleteParameters.java | 1 - .../service/flow/processor/Preprocessor.java | 2 +- .../ResultSetExportPreprocessor.java | 2 +- .../notification/helper/EventBuilder.java | 4 +- .../OnlineSchemaChangeFlowableTask.java | 2 +- .../onlineschemachange/OscService.java | 4 +- .../PartitionPlanScheduleService.java | 2 +- .../odc/service/quartz/OdcJobListener.java | 4 +- .../odc/service/schedule/ScheduleService.java | 76 +++++++------------ .../service/schedule/ScheduleTaskService.java | 8 +- .../ScheduleResponseMapperFactory.java | 39 +++++----- .../schedule/model/QuartzJobChangeReq.java | 3 +- .../schedule/model/QuartzKeyGenerator.java | 4 +- .../schedule/model/ScheduleChangeLog.java | 2 - .../schedule/model/ScheduleChangeParams.java | 2 - .../schedule/model/ScheduleChangeReq.java | 61 --------------- .../schedule/model/ScheduleDetailResp.java | 10 +-- .../model/ScheduleListAttributes.java | 27 ------- .../schedule/model/ScheduleListResp.java | 46 ----------- .../schedule/model/ScheduleMapper.java | 2 +- .../schedule/model/ScheduleOverview.java | 2 +- .../schedule/model/ScheduleTaskListResp.java | 45 ----------- .../model/ScheduleTaskListRespMapper.java | 36 --------- .../processor/AbstractDlmPreprocessor.java | 4 +- .../processor/CreateScheduleAspect.java | 25 +++--- .../processor/DataArchivePreprocessor.java | 6 +- .../processor/DataDeletePreprocessor.java | 6 +- .../schedule/processor/Preprocessor.java | 6 +- .../processor/ScheduleTaskPreprocessor.java | 2 +- 38 files changed, 128 insertions(+), 369 deletions(-) delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java index 23e99b8682..c159893806 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.oceanbase.odc.metadb.schedule; import java.util.Collections; diff --git a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java index a9d6b60c01..29f30a714b 100644 --- a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java +++ b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java @@ -38,8 +38,10 @@ import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; import com.oceanbase.odc.service.schedule.ScheduleService; import com.oceanbase.odc.service.schedule.model.CreateScheduleReq; +import com.oceanbase.odc.service.schedule.model.OperationType; import com.oceanbase.odc.service.schedule.model.QueryScheduleParams; import com.oceanbase.odc.service.schedule.model.ScheduleChangeLog; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; import com.oceanbase.odc.service.schedule.model.ScheduleOverview; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; @@ -77,7 +79,7 @@ public ListResponse listChangeLog(@PathVariable Long id) { @RequestMapping(value = "/schedules/{id:[\\d]+}/changes/{scheduleChangeLogId:[\\d]+}", method = RequestMethod.GET) public SuccessResponse getChangeLog(@PathVariable Long id, @PathVariable Long scheduleChangeLogId) { - throw new UnsupportedException(); + return Responses.success(scheduleService.getChangeLog(id, scheduleChangeLogId)); } // schedule task @@ -91,22 +93,23 @@ public void terminateTask(@PathVariable Long scheduleId, @PathVariable Long task @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/executions/latest/stop", method = RequestMethod.POST) public SuccessResponse stopTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - throw new UnsupportedException(); - + scheduleService.stopTask(scheduleId, taskId); + return Responses.success(Boolean.TRUE); } @ApiOperation(value = "StartTask", notes = "启动任务") @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/start", method = RequestMethod.POST) public SuccessResponse startTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - throw new UnsupportedException(); - + scheduleService.startTask(scheduleId, taskId); + return Responses.success(Boolean.TRUE); } @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/rollback", method = RequestMethod.POST) public SuccessResponse rollbackTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - throw new UnsupportedException(); + scheduleService.rollbackTask(scheduleId, taskId); + return Responses.success(Boolean.TRUE); } @@ -114,53 +117,53 @@ public SuccessResponse rollbackTask(@PathVariable Long scheduleId, @Pat method = RequestMethod.GET) public SuccessResponse getTaskLog(@PathVariable Long scheduleId, @PathVariable Long taskId, @RequestParam OdcTaskLogLevel logType) { - throw new UnsupportedException(); + return Responses.success(scheduleService.getLog(scheduleId, taskId, logType)); } @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/", method = RequestMethod.GET) public SuccessResponse detailScheduleTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { - throw new UnsupportedException(); + return Responses.success(scheduleService.detailScheduleTask(scheduleId, taskId)); } @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks", method = RequestMethod.GET) public PaginatedResponse listTask( @PageableDefault(size = Integer.MAX_VALUE, sort = {"id"}, direction = Direction.DESC) Pageable pageable, @PathVariable Long scheduleId) { - throw new UnsupportedException(); + return Responses.paginated(scheduleService.listScheduleTaskOverview(pageable, scheduleId)); } // schedule @RequestMapping(value = "/schedules/{id:[\\d]+}/terminate", method = RequestMethod.POST) public SuccessResponse terminateSchedule(@PathVariable("id") Long id) { - throw new UnsupportedException(); - + scheduleService.changeSchedule(ScheduleChangeParams.with(id, OperationType.TERMINATE)); + return Responses.success(Boolean.TRUE); } @RequestMapping(value = "/schedules/{id:[\\d]+}/pause", method = RequestMethod.POST) public SuccessResponse pauseSchedule(@PathVariable Long id) { - throw new UnsupportedException(); - + scheduleService.changeSchedule(ScheduleChangeParams.with(id, OperationType.PAUSE)); + return Responses.success(Boolean.TRUE); } @RequestMapping(value = "/schedules/{id:[\\d]+}/resume", method = RequestMethod.POST) public SuccessResponse resumeSchedule(@PathVariable Long id) { - throw new UnsupportedException(); - + scheduleService.changeSchedule(ScheduleChangeParams.with(id, OperationType.RESUME)); + return Responses.success(Boolean.TRUE); } @RequestMapping(value = "/schedules/{id:[\\d]+}", method = RequestMethod.PUT) public SuccessResponse updateSchedule(@PathVariable Long id, @RequestBody UpdateScheduleReq req) { - throw new UnsupportedException(); - + scheduleService.changeSchedule(ScheduleChangeParams.with(id, req)); + return Responses.success(Boolean.TRUE); } @RequestMapping(value = "/schedules", method = RequestMethod.POST) public SuccessResponse createSchedule(@RequestBody CreateScheduleReq req) { - throw new UnsupportedException(); - + scheduleService.changeSchedule(ScheduleChangeParams.with(req)); + return Responses.success(Boolean.TRUE); } @@ -192,7 +195,8 @@ public PaginatedResponse list( .creator(creator) .projectId(projectId) .build(); - throw new UnsupportedException(); + + return Responses.paginated(scheduleService.listScheduleOverview(pageable, req)); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java index 3856fc9743..3005d6bfbc 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.oceanbase.odc.metadb.schedule; import javax.persistence.Column; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java index 0cd6102e90..8be97d823f 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.oceanbase.odc.metadb.schedule; import java.util.List; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java index 05cce45e03..8e537ddd4a 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogEntity.java @@ -26,7 +26,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import com.oceanbase.odc.service.schedule.flowtask.OperationType; +import com.oceanbase.odc.service.schedule.model.OperationType; import com.oceanbase.odc.service.schedule.model.ScheduleChangeStatus; import lombok.Data; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java index 228f4a0596..2cb4a70dfb 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleEntity.java @@ -74,7 +74,7 @@ public class ScheduleEntity implements Serializable { @Enumerated(EnumType.STRING) @Column(name = "job_type", nullable = false) - private ScheduleType scheduleType; + private ScheduleType type; @Column(name = "job_parameters_json", nullable = false) private String jobParametersJson; @Column(name = "trigger_config_json", nullable = false) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java index aa5505ebc4..142508e044 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleRepository.java @@ -55,7 +55,7 @@ public interface ScheduleRepository extends OdcJpaRepository find(@NotNull Pageable pageable, @NotNull QueryScheduleParams params) { Specification specification = Specification .where(OdcJpaRepository.between(ScheduleEntity_.createTime, params.getStartTime(), params.getEndTime())) - .and(OdcJpaRepository.eq(ScheduleEntity_.scheduleType, params.getType())) + .and(OdcJpaRepository.eq(ScheduleEntity_.type, params.getType())) .and(OdcJpaRepository.in(ScheduleEntity_.projectId, params.getProjectIds())) .and(OdcJpaRepository.eq(ScheduleEntity_.id, params.getId())) .and(OdcJpaRepository.in(ScheduleEntity_.status, params.getStatuses())) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/DLMTableStructureSynchronizer.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/DLMTableStructureSynchronizer.java index 84b9945bf9..c01eeae2b8 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/DLMTableStructureSynchronizer.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/DLMTableStructureSynchronizer.java @@ -62,6 +62,10 @@ public static void sync(ConnectionConfig srcConfig, ConnectionConfig tgtConfig, String srcTableName, String tgtTableName, Set targetType) throws Exception { DataSource sourceDs = new DruidDataSourceFactory(srcConfig).getDataSource(); DataSource targetDs = new DruidDataSourceFactory(tgtConfig).getDataSource(); + if (srcConfig.getDialectType() != tgtConfig.getDialectType()) { + log.warn("Different types of databases do not support structural synchronization."); + return; + } try { String tgtDbVersion = getDBVersion(tgtConfig.getType(), targetDs); String srcDbVersion = getDBVersion(srcConfig.getType(), sourceDs); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java index 9af752e284..c27f87c19b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataArchiveParameters.java @@ -19,7 +19,6 @@ import java.util.List; import java.util.Set; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskParameters; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.schedule.model.ScheduleTaskParameters; import com.oceanbase.tools.dbbrowser.model.DBObjectType; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java index 01bdc5f32c..6739f7ae7a 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/DataDeleteParameters.java @@ -17,7 +17,6 @@ import java.util.List; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskParameters; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.schedule.model.ScheduleTaskParameters; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java index c31df2c2f1..ed7480e91b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/Preprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java index 2e12aa837f..b8b7735aa1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/processor/ResultSetExportPreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java index c0572dc54c..c4a0eb4c53 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/notification/helper/EventBuilder.java @@ -255,7 +255,7 @@ private Event ofScheduleTask(ScheduleTask scheduleTask, TaskEvent status) { labels.putIfNonNull(TASK_TYPE, scheduleTask.getJobGroup()); labels.putIfNonNull(TASK_ID, schedule.getId()); - labels.putIfNonNull(CONNECTION_ID, schedule.getConnectionId()); + labels.putIfNonNull(CONNECTION_ID, schedule.getDataSourceId()); labels.putIfNonNull(CREATOR_ID, schedule.getCreatorId()); labels.putIfNonNull(PROJECT_ID, schedule.getProjectId()); labels.putIfNonNull(DATABASE_ID, schedule.getDatabaseId()); @@ -280,7 +280,7 @@ private Event ofSchedule(ScheduleEntity schedule, TaskEvent status) { labels.putIfNonNull(REGION, OB_ARN_PARTITION); labels.putIfNonNull(DESCRIPTION, schedule.getDescription()); - labels.putIfNonNull(TASK_TYPE, schedule.getScheduleType()); + labels.putIfNonNull(TASK_TYPE, schedule.getType()); labels.putIfNonNull(TASK_ID, schedule.getId()); labels.putIfNonNull(CONNECTION_ID, schedule.getDataSourceId()); labels.putIfNonNull(CREATOR_ID, schedule.getCreatorId()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java index ef6340fe93..932fbd7dc8 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeFlowableTask.java @@ -272,7 +272,7 @@ private ScheduleEntity createScheduleEntity(ConnectionConfig connectionConfig, ScheduleEntity scheduleEntity = new ScheduleEntity(); scheduleEntity.setDataSourceId(connectionConfig.id()); scheduleEntity.setDatabaseName(schema); - scheduleEntity.setScheduleType(ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE); + scheduleEntity.setType(ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE); scheduleEntity.setStatus(ScheduleStatus.ENABLED); scheduleEntity.setAllowConcurrent(false); scheduleEntity.setCreatorId(creatorId); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java index 5a18446396..8a830ac25d 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/OscService.java @@ -134,8 +134,8 @@ public OscSwapTableVO swapTable(@PathVariable Long scheduleTaskId) { OnlineSchemaChangeScheduleTaskResult.class); PreConditions.validArgumentState( - scheduleEntity.get().getScheduleType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE, - ErrorCodes.BadArgument, new Object[] {scheduleEntity.get().getScheduleType()}, + scheduleEntity.get().getType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE, + ErrorCodes.BadArgument, new Object[] {scheduleEntity.get().getType()}, "Task type is not " + TaskType.ONLINE_SCHEMA_CHANGE.name()); SwapTableType swapTableType = oscParameters.getSwapTableType(); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java index c28dc51cae..d11091cc98 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java @@ -259,7 +259,7 @@ private ScheduleEntity createAndEnableSchedule(Database database, @NonNull Trigg scheduleEntity.setStatus(ScheduleStatus.ENABLED); scheduleEntity.setAllowConcurrent(false); scheduleEntity.setMisfireStrategy(MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING); - scheduleEntity.setScheduleType(ScheduleType.PARTITION_PLAN); + scheduleEntity.setType(ScheduleType.PARTITION_PLAN); scheduleEntity.setTriggerConfigJson(JsonUtils.toJson(triggerConfig)); scheduleEntity.setProjectId(database.getProject().getId()); scheduleEntity.setDataSourceId(database.getDataSource().getId()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java index 8d1175c88d..bcc0cec770 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/OdcJobListener.java @@ -86,10 +86,10 @@ public void jobToBeExecuted(JobExecutionContext context) { ScheduleEntity scheduleEntity = scheduleRepository.findById(scheduleId) .orElseThrow(() -> new NotFoundException(ResourceType.ODC_SCHEDULE, "id", scheduleId)); - ScheduleTaskContextHolder.trace(scheduleEntity.getId(), scheduleEntity.getScheduleType().name(), null); + ScheduleTaskContextHolder.trace(scheduleEntity.getId(), scheduleEntity.getType().name(), null); log.info("Job to be executed.OrganizationId={},ProjectId={},DatabaseId={},JobType={}", scheduleEntity.getOrganizationId(), scheduleEntity.getProjectId(), scheduleEntity.getDatabaseId(), - scheduleEntity.getScheduleType()); + scheduleEntity.getType()); UserEntity userEntity = userService.nullSafeGet(scheduleEntity.getCreatorId()); userEntity.setOrganizationId(scheduleEntity.getOrganizationId()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java index 26b2744137..2c9f080103 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java @@ -50,6 +50,7 @@ import com.oceanbase.odc.metadb.schedule.ScheduleRepository; import com.oceanbase.odc.service.collaboration.project.ProjectService; import com.oceanbase.odc.service.connection.database.DatabaseService; +import com.oceanbase.odc.service.flow.processor.EnablePreprocess; import com.oceanbase.odc.service.iam.OrganizationService; import com.oceanbase.odc.service.iam.ProjectPermissionValidator; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; @@ -60,23 +61,21 @@ import com.oceanbase.odc.service.regulation.approval.ApprovalFlowConfigSelector; import com.oceanbase.odc.service.schedule.factory.ScheduleResponseMapperFactory; import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; -import com.oceanbase.odc.service.schedule.model.CreateScheduleReq; import com.oceanbase.odc.service.schedule.model.OperationType; import com.oceanbase.odc.service.schedule.model.QuartzJobChangeReq; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.QueryScheduleParams; import com.oceanbase.odc.service.schedule.model.Schedule; import com.oceanbase.odc.service.schedule.model.ScheduleChangeLog; -import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; -import com.oceanbase.odc.service.schedule.model.ScheduleListResp; import com.oceanbase.odc.service.schedule.model.ScheduleMapper; +import com.oceanbase.odc.service.schedule.model.ScheduleOverview; import com.oceanbase.odc.service.schedule.model.ScheduleStatus; import com.oceanbase.odc.service.schedule.model.ScheduleTaskDetailResp; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskListResp; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskOverview; import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; -import com.oceanbase.odc.service.schedule.model.UpdateScheduleReq; import com.oceanbase.odc.service.task.model.OdcTaskLogLevel; import lombok.extern.slf4j.Slf4j; @@ -134,8 +133,9 @@ public class ScheduleService { private final ScheduleMapper scheduleMapper = ScheduleMapper.INSTANCE; + @EnablePreprocess @Transactional(rollbackFor = Exception.class) - public void changeSchedule(ScheduleChangeReq req) { + public void changeSchedule(ScheduleChangeParams req) { Schedule targetSchedule; @@ -147,7 +147,7 @@ public void changeSchedule(ScheduleChangeReq req) { entity.setDescription(req.getCreateScheduleReq().getDescription()); entity.setJobParametersJson(JsonUtils.toJson(req.getCreateScheduleReq().getParameters())); entity.setTriggerConfigJson(JsonUtils.toJson(req.getCreateScheduleReq().getTriggerConfig())); - entity.setScheduleType(req.getCreateScheduleReq().getType()); + entity.setType(req.getCreateScheduleReq().getType()); entity.setMisfireStrategy(MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING); entity.setStatus(ScheduleStatus.CREATING); @@ -157,7 +157,7 @@ public void changeSchedule(ScheduleChangeReq req) { entity.setModifierId(authenticationFacade.currentUserId()); entity.setDatabaseId(req.getCreateScheduleReq().getDatabaseId()); entity.setDatabaseName(req.getCreateScheduleReq().getDatabaseName()); - entity.setConnectionId(req.getCreateScheduleReq().getConnectionId()); + entity.setDataSourceId(req.getCreateScheduleReq().getConnectionId()); targetSchedule = scheduleMapper.entityToModel(scheduleRepository.save(entity)); req.setScheduleId(targetSchedule.getId()); @@ -178,16 +178,17 @@ public void changeSchedule(ScheduleChangeReq req) { // create change log for this request ScheduleChangeLog changeLog = scheduleChangeLogService.createChangeLog( - ScheduleChangeLog.build(targetSchedule.getId(), req.getOperationType(), targetSchedule.getParameters(), + ScheduleChangeLog.build(targetSchedule.getId(), req.getOperationType(), + JsonUtils.toJson(targetSchedule.getParameters()), req.getOperationType() == OperationType.UPDATE ? JsonUtils.toJson(req.getUpdateScheduleReq().getParameters()) - : targetSchedule.getParameters(), + : null, approvalFlowInstanceId)); log.info("Create change log success,changLog={}", changeLog); } - public void executeChangeSchedule(ScheduleChangeReq req) { + public void executeChangeSchedule(ScheduleChangeParams req) { Schedule targetSchedule = nullSafeGetModelById(req.getScheduleId()); // start to change schedule switch (req.getOperationType()) { @@ -218,8 +219,8 @@ public void executeChangeSchedule(ScheduleChangeReq req) { QuartzJobChangeReq quartzJobReq = new QuartzJobChangeReq(); quartzJobReq.setOperationType(req.getOperationType()); quartzJobReq.setJobName(targetSchedule.getId().toString()); - quartzJobReq.setJobGroup(targetSchedule.getScheduleType().name()); - quartzJobReq.setTriggerConfig(JsonUtils.fromJson(targetSchedule.getTriggerConfigJson(), TriggerConfig.class)); + quartzJobReq.setJobGroup(targetSchedule.getType().name()); + quartzJobReq.setTriggerConfig(targetSchedule.getTriggerConfig()); quartzJobService.changeQuartzJob(quartzJobReq); } @@ -241,12 +242,14 @@ public void innerUpdateTriggerData(Long scheduleId, Map triggerD quartzJobService.rescheduleJob(scheduleTrigger.getKey(), scheduleTrigger); } + @Deprecated @Transactional(rollbackFor = Exception.class) public void enable(ScheduleEntity scheduleConfig) throws SchedulerException, ClassNotFoundException { quartzJobService.createJob(buildCreateJobReq(scheduleConfig)); scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.ENABLED); } + @Deprecated @Transactional(rollbackFor = Exception.class) public void innerEnable(Long scheduleId, Map triggerDataMap) throws SchedulerException { @@ -255,6 +258,7 @@ public void innerEnable(Long scheduleId, Map triggerDataMap) scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.ENABLED); } + @Deprecated @Transactional(rollbackFor = Exception.class) public void pause(ScheduleEntity scheduleConfig) throws SchedulerException { Trigger scheduleTrigger = nullSafeGetScheduleTrigger(scheduleConfig); @@ -262,6 +266,7 @@ public void pause(ScheduleEntity scheduleConfig) throws SchedulerException { scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.PAUSE); } + @Deprecated @Transactional(rollbackFor = Exception.class) public void resume(ScheduleEntity scheduleConfig) throws SchedulerException { Trigger scheduleTrigger = getScheduleTrigger(scheduleConfig); @@ -273,6 +278,7 @@ public void resume(ScheduleEntity scheduleConfig) throws SchedulerException { scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.ENABLED); } + @Deprecated @Transactional(rollbackFor = Exception.class) public void terminate(ScheduleEntity scheduleConfig) throws SchedulerException { JobKey jobKey = QuartzKeyGenerator.generateJobKey(scheduleConfig); @@ -280,27 +286,6 @@ public void terminate(ScheduleEntity scheduleConfig) throws SchedulerException { scheduleRepository.updateStatusById(scheduleConfig.getId(), ScheduleStatus.TERMINATED); } - public void create(CreateScheduleReq req) { - changeSchedule(ScheduleChangeReq.with(req)); - } - - public void pause(Long scheduleId) { - changeSchedule(ScheduleChangeReq.with(scheduleId, OperationType.TERMINATE)); - } - - public void update(Long scheduleId, UpdateScheduleReq req) { - changeSchedule(ScheduleChangeReq.with(scheduleId, req)); - } - - public void resume(Long scheduleId) { - changeSchedule(ScheduleChangeReq.with(scheduleId, OperationType.TERMINATE)); - } - - public void terminate(Long scheduleId) { - changeSchedule(ScheduleChangeReq.with(scheduleId, OperationType.TERMINATE)); - } - - /** * The method detects whether the database required for scheduled task operation exists. It returns * true and terminates the scheduled task if the database does not exist. If the database exists, it @@ -316,7 +301,7 @@ public boolean terminateIfScheduleInvalid(Long scheduleId) { log.info( "The project or database for scheduled task operation does not exist, and the schedule is being terminated, scheduleId={}", scheduleId); - terminate(scheduleId); + terminate(entity); } catch (Exception e) { log.warn("Terminate schedule failed,scheduleId={}", scheduleId); } @@ -362,18 +347,9 @@ public void startTask(Long scheduleId, Long scheduleTaskId) { scheduleTaskService.start(scheduleTaskId); } - public void dataArchiveDelete(Long scheduleId, Long taskId) { - ScheduleEntity scheduleEntity = nullSafeGetById(scheduleId); - if (scheduleEntity.getScheduleType() != ScheduleType.DATA_ARCHIVE) { - throw new UnsupportedException(); - } - - - } - public void rollbackTask(Long scheduleId, Long scheduleTaskId) { Schedule schedule = nullSafeGetByIdWithCheckPermission(scheduleId, true); - if (schedule.getScheduleType() != ScheduleType.DATA_ARCHIVE) { + if (schedule.getType() != ScheduleType.DATA_ARCHIVE) { throw new UnsupportedException(); } scheduleTaskService.rollbackTask(scheduleTaskId); @@ -443,7 +419,8 @@ public ScheduleDetailResp detailSchedule(Long scheduleId) { return scheduleResponseMapperFactory.generateScheduleDetailResp(schedule); } - public Page getScheduleListResp(@NotNull Pageable pageable, @NotNull QueryScheduleParams params) { + public Page listScheduleOverview(@NotNull Pageable pageable, + @NotNull QueryScheduleParams params) { if (authenticationFacade.currentOrganization().getType() == OrganizationType.TEAM) { Set projectIds = params.getProjectId() == null @@ -457,13 +434,14 @@ public Page getScheduleListResp(@NotNull Pageable pageable, @N params.setOrganizationId(authenticationFacade.currentOrganizationId()); Page returnValue = scheduleRepository.find(pageable, params); - List res = scheduleResponseMapperFactory.generateListResponse(returnValue.getContent()); + List res = + scheduleResponseMapperFactory.generateScheduleOverviewList(returnValue.getContent()); return returnValue.isEmpty() ? Page.empty() : new PageImpl<>(res, returnValue.getPageable(), returnValue.getTotalPages()); } - public Page listScheduleTask(@NotNull Pageable pageable, @NotNull Long scheduleId) { + public Page listScheduleTaskOverview(@NotNull Pageable pageable, @NotNull Long scheduleId) { nullSafeGetByIdWithCheckPermission(scheduleId, false); return scheduleTaskService.getScheduleTaskListResp(pageable, scheduleId); } @@ -532,7 +510,7 @@ private CreateQuartzJobReq buildCreateJobReq(ScheduleEntity schedule) { CreateQuartzJobReq createQuartzJobReq = new CreateQuartzJobReq(); createQuartzJobReq.setJobKey(QuartzKeyGenerator.generateJobKey(schedule)); createQuartzJobReq.setTriggerConfig(JsonUtils.fromJson(schedule.getTriggerConfigJson(), TriggerConfig.class)); - if (schedule.getScheduleType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE) { + if (schedule.getType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE) { createQuartzJobReq.getJobDataMap().putAll(JsonUtils.fromJson(schedule.getJobParametersJson(), Map.class)); } else { createQuartzJobReq.getJobDataMap().putAll(BeanMap.create(schedule)); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java index 89cd7b4867..018c3d1c3e 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java @@ -61,9 +61,9 @@ import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.ScheduleTask; import com.oceanbase.odc.service.schedule.model.ScheduleTaskDetailResp; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskListResp; -import com.oceanbase.odc.service.schedule.model.ScheduleTaskListRespMapper; import com.oceanbase.odc.service.schedule.model.ScheduleTaskMapper; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskOverview; +import com.oceanbase.odc.service.schedule.model.ScheduleTaskOverviewMapper; import com.oceanbase.odc.service.schedule.model.ScheduleTaskType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import com.oceanbase.odc.service.schedule.model.TriggerStrategy; @@ -222,8 +222,8 @@ public Page list(Pageable pageable, Long scheduleId) { return scheduleTaskRepository.findAll(specification, pageable).map(scheduleTaskMapper::entityToModel); } - public Page getScheduleTaskListResp(Pageable pageable, Long scheduleId) { - return list(pageable, scheduleId).map(ScheduleTaskListRespMapper::map); + public Page getScheduleTaskListResp(Pageable pageable, Long scheduleId) { + return list(pageable, scheduleId).map(ScheduleTaskOverviewMapper::map); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java index 287b4b0d55..6dccbfc5ec 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.alibaba.fastjson.JSON; import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.metadb.iam.UserRepository; import com.oceanbase.odc.metadb.schedule.LatestScheduleTaskLinkEntity; @@ -47,10 +48,9 @@ import com.oceanbase.odc.service.schedule.model.DataDeleteAttributes; import com.oceanbase.odc.service.schedule.model.Schedule; import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; -import com.oceanbase.odc.service.schedule.model.ScheduleListAttributes; -import com.oceanbase.odc.service.schedule.model.ScheduleListResp; +import com.oceanbase.odc.service.schedule.model.ScheduleOverview; +import com.oceanbase.odc.service.schedule.model.ScheduleOverviewAttributes; import com.oceanbase.odc.service.schedule.model.ScheduleType; -import com.oceanbase.odc.service.schedule.model.TriggerConfig; import lombok.NonNull; @@ -84,11 +84,11 @@ public ScheduleDetailResp generateScheduleDetailResp(@NonNull Schedule schedule) ScheduleDetailResp scheduleDetailResp = new ScheduleDetailResp(); scheduleDetailResp.setScheduleId(schedule.getId()); - scheduleDetailResp.setTriggerConfig(schedule.getTriggerConfigJson()); + scheduleDetailResp.setTriggerConfig(schedule.getTriggerConfig()); scheduleDetailResp.setMisfireStrategy(schedule.getMisfireStrategy()); scheduleDetailResp.setAllowConcurrent(schedule.getAllowConcurrent()); - scheduleDetailResp.setType(schedule.getScheduleType()); + scheduleDetailResp.setType(schedule.getType()); scheduleDetailResp.setStatus(schedule.getStatus()); scheduleDetailResp.setCreateTime(schedule.getCreateTime()); scheduleDetailResp.setUpdateTime(schedule.getUpdateTime()); @@ -96,18 +96,17 @@ public ScheduleDetailResp generateScheduleDetailResp(@NonNull Schedule schedule) scheduleDetailResp.setDescription(schedule.getDescription()); scheduleDetailResp.setNextFireTimes( - QuartzCronExpressionUtils.getNextFiveFireTimes(JsonUtils.fromJson(schedule.getTriggerConfigJson(), - TriggerConfig.class).getCronExpression())); + QuartzCronExpressionUtils.getNextFiveFireTimes(schedule.getTriggerConfig().getCronExpression())); userRepository.findById(schedule.getCreatorId()) .ifPresent(o -> scheduleDetailResp.setCreator(new InnerUser(o, null))); - scheduleDetailResp.setType(schedule.getScheduleType()); + scheduleDetailResp.setType(schedule.getType()); scheduleDetailResp.setParameters(schedule.getParameters()); return scheduleDetailResp; } - public List generateListResponse(@NonNull Collection schedules) { + public List generateScheduleOverviewList(@NonNull Collection schedules) { if (schedules.isEmpty()) { return Collections.emptyList(); @@ -127,25 +126,25 @@ public List generateListResponse(@NonNull Collection Long.valueOf(o.getJobName()), o -> o)); - Map id2Attributes = generateAttributes(schedules); + Map id2Attributes = generateAttributes(schedules); return schedules.stream().map(o -> { - ScheduleListResp scheduleListResp = new ScheduleListResp(); - scheduleListResp.setScheduleId(o.getId()); - scheduleListResp.setStatus(o.getStatus()); - scheduleListResp.setAttributes(id2Attributes.get(o.getId())); + ScheduleOverview overview = new ScheduleOverview(); + overview.setScheduleId(o.getId()); + overview.setStatus(o.getStatus()); + overview.setAttributes(JSON.parseObject(JSON.toJSONString(id2Attributes.get(o.getId())))); if (scheduleId2ScheduleTaskId.containsKey(o.getId())) { ScheduleTaskEntity scheduleTask = scheduleId2ScheduleTask.get(o.getId()); - scheduleListResp.setLatestFireTime(scheduleTask.getFireTime()); - scheduleListResp.setLatestExecutionStatus(scheduleTask.getStatus()); + overview.setLatestFireTime(scheduleTask.getFireTime()); + overview.setLatestExecutionStatus(scheduleTask.getStatus()); } - return scheduleListResp; + return overview; }).collect(Collectors.toList()); } - private Map generateAttributes(Collection schedules) { + private Map generateAttributes(Collection schedules) { Map> type2Entity = schedules.stream().collect( - Collectors.groupingBy(ScheduleEntity::getScheduleType)); - Map id2Attributes = new HashMap<>(); + Collectors.groupingBy(ScheduleEntity::getType)); + Map id2Attributes = new HashMap<>(); type2Entity.forEach((k, v) -> { switch (k) { case DATA_DELETE: { diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java index 42d72f54b1..fe837bc654 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.oceanbase.odc.service.schedule.model; import org.quartz.JobDataMap; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java index ae85d7f564..533b8b2431 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzKeyGenerator.java @@ -29,11 +29,11 @@ public class QuartzKeyGenerator { public static TriggerKey generateTriggerKey(ScheduleEntity schedule) { - return new TriggerKey(schedule.getId().toString(), schedule.getScheduleType().name()); + return new TriggerKey(schedule.getId().toString(), schedule.getType().name()); } public static JobKey generateJobKey(ScheduleEntity schedule) { - return new JobKey(schedule.getId().toString(), schedule.getScheduleType().name()); + return new JobKey(schedule.getId().toString(), schedule.getType().name()); } public static TriggerKey generateTriggerKey(Long scheduleId, JobType jobType) { diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java index b5ba106839..deba4821c9 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java @@ -17,8 +17,6 @@ import java.util.Date; -import com.oceanbase.odc.service.schedule.flowtask.OperationType; - import lombok.Data; /** diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeParams.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeParams.java index 3610650ac6..1e4e3abbbb 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeParams.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeParams.java @@ -15,8 +15,6 @@ */ package com.oceanbase.odc.service.schedule.model; -import com.oceanbase.odc.service.schedule.flowtask.OperationType; - import lombok.Data; /** diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java deleted file mode 100644 index 222c6ba3aa..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeReq.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.oceanbase.odc.service.schedule.model; - -import lombok.Data; - -/** - * @Author:tinker - * @Date: 2024/6/25 19:34 - * @Descripition: - */ - -@Data -public class ScheduleChangeReq { - - private Long scheduleId; - - private OperationType operationType; - - private CreateScheduleReq createScheduleReq; - - private UpdateScheduleReq updateScheduleReq; - - public static ScheduleChangeReq with(Long id, OperationType type) { - ScheduleChangeReq req = new ScheduleChangeReq(); - req.setScheduleId(id); - req.setOperationType(type); - return req; - } - - public static ScheduleChangeReq with(CreateScheduleReq createScheduleReq) { - ScheduleChangeReq req = new ScheduleChangeReq(); - req.setOperationType(OperationType.CREATE); - req.setCreateScheduleReq(createScheduleReq); - return req; - } - - public static ScheduleChangeReq with(Long id, UpdateScheduleReq updateScheduleReq) { - ScheduleChangeReq req = new ScheduleChangeReq(); - req.setScheduleId(id); - req.setOperationType(OperationType.UPDATE); - req.setUpdateScheduleReq(updateScheduleReq); - return req; - } - - -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java index 587cf89e29..b9354c4e11 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleDetailResp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ import java.util.Date; import java.util.List; -import com.fasterxml.jackson.annotation.JsonRawValue; import com.oceanbase.odc.common.i18n.Internationalizable; import com.oceanbase.odc.service.common.model.InnerUser; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; @@ -57,9 +56,8 @@ public class ScheduleDetailResp { private List nextFireTimes; - @JsonRawValue - private String parameters; - @JsonRawValue - private String triggerConfig; + private ScheduleTaskParameters parameters; + + private TriggerConfig triggerConfig; } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java deleted file mode 100644 index 1355f2ddc4..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListAttributes.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.oceanbase.odc.service.schedule.model; - -/** - * @Author:tinker - * @Date: 2024/6/10 17:28 - * @Descripition: - */ -public interface ScheduleListAttributes { - - -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java deleted file mode 100644 index 27a918d5d9..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleListResp.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2024 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.oceanbase.odc.service.schedule.model; - -import java.util.Date; - -import com.oceanbase.odc.core.shared.constant.TaskStatus; - -import lombok.Data; - -/** - * @Author:tinker - * @Date: 2024/6/8 13:30 - * @Descripition: - */ - - - -@Data -public class ScheduleListResp { - - private Long scheduleId; - - private ScheduleListAttributes attributes; - - private ScheduleStatus status; - - private Date latestFireTime; - - private TaskStatus latestExecutionStatus; - -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java index 6401c27bb3..d24147280c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleMapper.java @@ -45,7 +45,7 @@ public interface ScheduleMapper { @Named("entityToParameters") default ScheduleTaskParameters entityToParameters(ScheduleEntity entity) { - switch (entity.getJobType()) { + switch (entity.getType()) { case DATA_ARCHIVE: return JsonUtils.fromJson(entity.getJobParametersJson(), DataArchiveParameters.class); case DATA_DELETE: diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleOverview.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleOverview.java index 540ed8436b..86cbd9022f 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleOverview.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleOverview.java @@ -35,7 +35,7 @@ public class ScheduleOverview { private Long scheduleId; - private Map attributes; + private Map attributes; private ScheduleStatus status; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java deleted file mode 100644 index 6256c14026..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListResp.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2024 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.oceanbase.odc.service.schedule.model; - -import java.util.Date; - -import com.oceanbase.odc.core.shared.constant.TaskStatus; - -import lombok.Data; - -/** - * @Author:tinker - * @Date: 2024/6/19 14:31 - * @Descripition: - */ - - -@Data -public class ScheduleTaskListResp { - - private Long id; - - private ScheduleTaskType type; - - private TaskStatus status; - - private Date createTime; - - private Date updateTime; - -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java deleted file mode 100644 index 6ae727abbd..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleTaskListRespMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2024 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.oceanbase.odc.service.schedule.model; - -/** - * @Author:tinker - * @Date: 2024/6/19 15:35 - * @Descripition: - */ -public class ScheduleTaskListRespMapper { - - public static ScheduleTaskListResp map(ScheduleTask scheduleTask) { - ScheduleTaskListResp t = new ScheduleTaskListResp(); - t.setId(scheduleTask.getId()); - t.setStatus(scheduleTask.getStatus()); - t.setType(ScheduleTaskType.valueOf(scheduleTask.getJobGroup())); - t.setCreateTime(scheduleTask.getCreateTime()); - t.setUpdateTime(scheduleTask.getUpdateTime()); - return t; - } - -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java index 8471f0b88c..05d8078e0a 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/AbstractDlmPreprocessor.java @@ -33,7 +33,7 @@ import com.oceanbase.odc.service.dlm.model.OffsetConfig; import com.oceanbase.odc.service.dlm.model.RateLimitConfiguration; import com.oceanbase.odc.service.dlm.utils.DataArchiveConditionUtil; -import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.tools.dbbrowser.util.MySQLSqlBuilder; import com.oceanbase.tools.dbbrowser.util.OracleSqlBuilder; import com.oceanbase.tools.dbbrowser.util.SqlBuilder; @@ -50,7 +50,7 @@ public class AbstractDlmPreprocessor implements Preprocessor { @Override - public void process(ScheduleChangeReq req) {} + public void process(ScheduleChangeParams req) {} public void checkTableAndCondition(ConnectionSession connectionSession, Database sourceDb, List tables, diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java index 26a8a80b65..8189d9365b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.oceanbase.odc.service.schedule.processor; import java.util.HashMap; @@ -21,58 +20,60 @@ import java.util.Map; import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import com.oceanbase.odc.core.shared.exception.UnsupportedException; -import com.oceanbase.odc.service.collaboration.project.ProjectService; import com.oceanbase.odc.service.connection.database.DatabaseService; import com.oceanbase.odc.service.connection.database.model.Database; import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; -import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; import com.oceanbase.odc.service.schedule.ScheduleService; import com.oceanbase.odc.service.schedule.model.CreateScheduleReq; import com.oceanbase.odc.service.schedule.model.OperationType; -import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.odc.service.schedule.model.ScheduleType; +import lombok.extern.slf4j.Slf4j; + /** * @Author:tinker * @Date: 2024/6/25 17:01 * @Descripition: */ + +@Slf4j +@Aspect +@Component public class CreateScheduleAspect implements InitializingBean { @Autowired private DatabaseService databaseService; @Autowired - private AuthenticationFacade authenticationFacade; - @Autowired private ScheduleService scheduleService; @Autowired private List preprocessors; - @Autowired - private ProjectService projectService; private final Map type2Processor = new HashMap<>(); - @Pointcut("@annotation(com.oceanbase.odc.service.flow.processor.EnablePreprocess) && args(com.oceanbase.odc.service.schedule.model.ScheduleChangeReq)") + @Pointcut("@annotation(com.oceanbase.odc.service.flow.processor.EnablePreprocess) && args(com.oceanbase.odc.service.schedule.model.ScheduleChangeParams)") public void processBeforeChangeSchedule() {} @Before("processBeforeChangeSchedule()") public void createPreprocess(JoinPoint point) throws Throwable { - ScheduleChangeReq req = (ScheduleChangeReq) point.getArgs()[0]; + ScheduleChangeParams req = (ScheduleChangeParams) point.getArgs()[0]; ScheduleType type; if (req.getOperationType() == OperationType.CREATE) { type = req.getCreateScheduleReq().getType(); adaptCreateScheduleReq(req.getCreateScheduleReq()); } else { - type = scheduleService.nullSafeGetModelById(req.getScheduleId()).getScheduleType(); + type = scheduleService.nullSafeGetModelById(req.getScheduleId()).getType(); } if (type2Processor.containsKey(type)) { type2Processor.get(type).process(req); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java index 7071a8f5f1..6cc1ac42c1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; import com.oceanbase.odc.service.plugin.ConnectionPluginUtil; import com.oceanbase.odc.service.schedule.model.OperationType; -import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.session.factory.DefaultConnectSessionFactory; @@ -60,7 +60,7 @@ public class DataArchivePreprocessor extends AbstractDlmPreprocessor { private DLMConfiguration dlmConfiguration; @Override - public void process(ScheduleChangeReq req) { + public void process(ScheduleChangeParams req) { if (req.getOperationType() == OperationType.CREATE || req.getOperationType() == OperationType.UPDATE) { DataArchiveParameters parameters = req.getOperationType() == OperationType.CREATE ? (DataArchiveParameters) req.getCreateScheduleReq().getParameters() diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java index e43e7898a4..d3a7f69c33 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; import com.oceanbase.odc.service.schedule.model.OperationType; -import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.session.factory.DefaultConnectSessionFactory; @@ -57,7 +57,7 @@ public class DataDeletePreprocessor extends AbstractDlmPreprocessor { private DLMConfiguration dlmConfiguration; @Override - public void process(ScheduleChangeReq req) { + public void process(ScheduleChangeParams req) { if (req.getOperationType() == OperationType.CREATE || req.getOperationType() == OperationType.UPDATE) { DataDeleteParameters parameters = req.getOperationType() == OperationType.CREATE ? (DataDeleteParameters) req.getCreateScheduleReq().getParameters() diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java index 302414645e..e0ba7719c9 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/Preprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ package com.oceanbase.odc.service.schedule.processor; -import com.oceanbase.odc.service.schedule.model.ScheduleChangeReq; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; /** * @Author:tinker @@ -24,6 +24,6 @@ */ public interface Preprocessor { - void process(ScheduleChangeReq req); + void process(ScheduleChangeParams req); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java index 71966287e6..0b191c5008 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleTaskPreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 13d14b8d770addec06d870aae360c7db2e6cab94 Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 27 Jun 2024 22:49:43 +0800 Subject: [PATCH 03/18] bugfix --- .../LatestScheduleTaskLinkRepositoryTest.java | 56 ------------------- .../LatestScheduleTaskLinkEntity.java | 48 ---------------- .../LatestScheduleTaskLinkRepository.java | 33 ----------- .../ScheduleResponseMapperFactory.java | 12 ++-- 4 files changed, 6 insertions(+), 143 deletions(-) delete mode 100644 server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java delete mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java deleted file mode 100644 index c159893806..0000000000 --- a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepositoryTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.oceanbase.odc.metadb.schedule; - -import java.util.Collections; -import java.util.List; - -import org.junit.Test; -import org.locationtech.jts.util.Assert; -import org.springframework.beans.factory.annotation.Autowired; - -import com.oceanbase.odc.ServiceTestEnv; - -/** - * @Author:tinker - * @Date: 2024/6/20 15:44 - * @Descripition: - */ -public class LatestScheduleTaskLinkRepositoryTest extends ServiceTestEnv { - - @Autowired - private LatestScheduleTaskLinkRepository repository; - - @Test - public void listByScheduleIds() { - LatestScheduleTaskLinkEntity entity = create(); - List entities = repository.findByScheduleIdIn(Collections.singleton(1L)); - Assert.equals(1, entities.size()); - Assert.equals(entity, entities.get(0)); - delete(entity); - } - - private LatestScheduleTaskLinkEntity create() { - LatestScheduleTaskLinkEntity entity = new LatestScheduleTaskLinkEntity(); - entity.setScheduleId(1L); - entity.setScheduleTaskId(99L); - return repository.save(entity); - } - - private void delete(LatestScheduleTaskLinkEntity entity) { - repository.delete(entity); - } -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java deleted file mode 100644 index 3005d6bfbc..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkEntity.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2023 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.oceanbase.odc.metadb.schedule; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; - -import lombok.Data; - -/** - * @Author:tinker - * @Date: 2024/6/10 17:51 - * @Descripition: - */ - -@Entity -@Data -@Table(name = "schedule_latest_schedule_task_link") -public class LatestScheduleTaskLinkEntity { - - @Id - @Column(name = "id", nullable = false) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "schedule_id", nullable = false) - private Long scheduleId; - - @Column(name = "schedule_task_id", nullable = false) - private Long scheduleTaskId; -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java deleted file mode 100644 index 8be97d823f..0000000000 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/LatestScheduleTaskLinkRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 OceanBase. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.oceanbase.odc.metadb.schedule; - -import java.util.List; -import java.util.Set; - -import com.oceanbase.odc.config.jpa.OdcJpaRepository; - -/** - * @Author:tinker - * @Date: 2024/6/10 18:58 - * @Descripition: - */ -public interface LatestScheduleTaskLinkRepository extends OdcJpaRepository { - - Long getScheduleTaskIdByScheduleId(Long scheduleId); - - List findByScheduleIdIn(Set scheduleIds); -} diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java index 6dccbfc5ec..86f8c1b878 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java @@ -30,8 +30,8 @@ import com.alibaba.fastjson.JSON; import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.metadb.iam.UserRepository; -import com.oceanbase.odc.metadb.schedule.LatestScheduleTaskLinkEntity; -import com.oceanbase.odc.metadb.schedule.LatestScheduleTaskLinkRepository; +import com.oceanbase.odc.metadb.schedule.LatestTaskMappingEntity; +import com.oceanbase.odc.metadb.schedule.LatestTaskMappingRepository; import com.oceanbase.odc.metadb.schedule.ScheduleEntity; import com.oceanbase.odc.metadb.schedule.ScheduleTaskEntity; import com.oceanbase.odc.metadb.schedule.ScheduleTaskRepository; @@ -76,7 +76,7 @@ public class ScheduleResponseMapperFactory { private ScheduleTaskRepository scheduleTaskRepository; @Autowired - private LatestScheduleTaskLinkRepository latestScheduleTaskLinkRepository; + private LatestTaskMappingRepository latestTaskMappingRepository; @@ -115,9 +115,9 @@ public List generateScheduleOverviewList(@NonNull Collection scheduleIds = schedules.stream().map(ScheduleEntity::getId).collect(Collectors.toSet()); Map scheduleId2ScheduleTaskId = - latestScheduleTaskLinkRepository.findByScheduleIdIn(scheduleIds).stream().collect( - Collectors.toMap(LatestScheduleTaskLinkEntity::getScheduleId, - LatestScheduleTaskLinkEntity::getScheduleTaskId)); + latestTaskMappingRepository.findByScheduleIdIn(scheduleIds).stream().collect( + Collectors.toMap(LatestTaskMappingEntity::getScheduleId, + LatestTaskMappingEntity::getLatestScheduleTaskId)); Map scheduleId2ScheduleTask = scheduleId2ScheduleTaskId.isEmpty() ? Collections.EMPTY_MAP From 67e2305625186bbb2d6242bee0f23edf4c477790 Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 27 Jun 2024 23:02:24 +0800 Subject: [PATCH 04/18] bugfix --- .../odc/service/schedule/processor/CreateScheduleAspect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java index 8189d9365b..88b3a75cdf 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java @@ -107,7 +107,7 @@ private void adaptCreateScheduleReq(CreateScheduleReq req) { req.setEnvironmentId(srcDb.getEnvironment().getId()); req.setEnvironmentName(srcDb.getEnvironment().getName()); req.setDatabaseName(srcDb.getName()); - req.setDatabaseId(req.getDatabaseId()); + req.setDatabaseId(srcDb.getId()); } private Long getTargetDatabaseId(CreateScheduleReq req) { From f9ff2321f41e8a884b61b2a3cc9a7a3347a48db5 Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 27 Jun 2024 23:17:06 +0800 Subject: [PATCH 05/18] bugfix --- .../odc/server/web/controller/v2/ScheduleController.java | 6 +++--- .../com/oceanbase/odc/service/schedule/ScheduleService.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java index 29f30a714b..ff3f943b9b 100644 --- a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java +++ b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java @@ -40,6 +40,7 @@ import com.oceanbase.odc.service.schedule.model.CreateScheduleReq; import com.oceanbase.odc.service.schedule.model.OperationType; import com.oceanbase.odc.service.schedule.model.QueryScheduleParams; +import com.oceanbase.odc.service.schedule.model.Schedule; import com.oceanbase.odc.service.schedule.model.ScheduleChangeLog; import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; @@ -161,9 +162,8 @@ public SuccessResponse updateSchedule(@PathVariable Long id, @RequestBo } @RequestMapping(value = "/schedules", method = RequestMethod.POST) - public SuccessResponse createSchedule(@RequestBody CreateScheduleReq req) { - scheduleService.changeSchedule(ScheduleChangeParams.with(req)); - return Responses.success(Boolean.TRUE); + public SuccessResponse createSchedule(@RequestBody CreateScheduleReq req) { + return Responses.success(scheduleService.changeSchedule(ScheduleChangeParams.with(req))); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java index 2c9f080103..2ac70e7ebd 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java @@ -135,7 +135,7 @@ public class ScheduleService { @EnablePreprocess @Transactional(rollbackFor = Exception.class) - public void changeSchedule(ScheduleChangeParams req) { + public Schedule changeSchedule(ScheduleChangeParams req) { Schedule targetSchedule; @@ -185,7 +185,7 @@ public void changeSchedule(ScheduleChangeParams req) { : null, approvalFlowInstanceId)); log.info("Create change log success,changLog={}", changeLog); - + return targetSchedule; } public void executeChangeSchedule(ScheduleChangeParams req) { From 57b89eb7f8df14b77280a53e222088412bf7b481 Mon Sep 17 00:00:00 2001 From: tinker Date: Fri, 28 Jun 2024 00:18:50 +0800 Subject: [PATCH 06/18] bugfix --- .../odc/server/web/controller/v2/ScheduleController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java index ff3f943b9b..942841464c 100644 --- a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java +++ b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java @@ -74,7 +74,8 @@ public class ScheduleController { @RequestMapping(value = "/schedules/{id:[\\d]+}/changes", method = RequestMethod.GET) public ListResponse listChangeLog(@PathVariable Long id) { - throw new UnsupportedException(); + return Responses.list(scheduleService.listScheduleChangeLog(id)); + } @RequestMapping(value = "/schedules/{id:[\\d]+}/changes/{scheduleChangeLogId:[\\d]+}", method = RequestMethod.GET) @@ -202,7 +203,7 @@ public PaginatedResponse list( @RequestMapping(value = "/schedules/{id:[\\d]+}", method = RequestMethod.GET) public SuccessResponse detailSchedule(@PathVariable Long id) { - throw new UnsupportedException(); + return Responses.success(scheduleService.detailSchedule(id)); } @RequestMapping(value = "/schedules/{id:[\\d]+}/dlmRateLimitConfiguration", method = RequestMethod.PUT) From 9d16f49c7997c2738410b346f7629f3c38e48aee Mon Sep 17 00:00:00 2001 From: tinker Date: Fri, 28 Jun 2024 00:43:03 +0800 Subject: [PATCH 07/18] bugfix --- .../odc/server/web/controller/v2/ScheduleController.java | 2 +- .../oceanbase/odc/service/schedule/model/ScheduleChangeLog.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java index 942841464c..5bdc7d26a0 100644 --- a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java +++ b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/ScheduleController.java @@ -123,7 +123,7 @@ public SuccessResponse getTaskLog(@PathVariable Long scheduleId, @PathVa } - @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}/", method = RequestMethod.GET) + @RequestMapping(value = "/schedules/{scheduleId:[\\d]+}/tasks/{taskId:[\\d]+}", method = RequestMethod.GET) public SuccessResponse detailScheduleTask(@PathVariable Long scheduleId, @PathVariable Long taskId) { return Responses.success(scheduleService.detailScheduleTask(scheduleId, taskId)); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java index deba4821c9..732ef3694b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java @@ -56,7 +56,7 @@ public static ScheduleChangeLog build(Long scheduleId, OperationType type, Strin String newParameters, Long flowInstanceId) { ScheduleChangeLog log = new ScheduleChangeLog(); log.setScheduleId(scheduleId); - log.setStatus(ScheduleChangeStatus.PREPARING); + log.setStatus(ScheduleChangeStatus.SUCCESS); log.setType(type); log.setOldScheduleParameterJson(oldParameters); log.setNewScheduleParameterJson(newParameters); From 568677d9a68d4a5e55dcadffb68352d728391df5 Mon Sep 17 00:00:00 2001 From: tinker Date: Fri, 28 Jun 2024 00:54:29 +0800 Subject: [PATCH 08/18] bugfix --- .../oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java | 2 +- .../oceanbase/odc/service/schedule/ScheduleTaskService.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java index 548058aaee..63475abba2 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/metadb/schedule/ScheduleTaskRepository.java @@ -39,7 +39,7 @@ public interface ScheduleTaskRepository extends JpaRepository, JpaSpecificationExecutor { - Optional findByIdAndJobName(Long id, Long scheduleId); + Optional findByIdAndJobName(Long id, String scheduleId); List findByJobNameAndStatusIn(String jobName, List statuses); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java index 018c3d1c3e..7de1a42f17 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java @@ -256,7 +256,8 @@ public ScheduleTaskEntity nullSafeGetById(Long id) { } public ScheduleTask nullSafeGetByIdAndScheduleId(Long id, Long scheduleId) { - Optional scheduleEntityOptional = scheduleTaskRepository.findByIdAndJobName(id, scheduleId); + Optional scheduleEntityOptional = + scheduleTaskRepository.findByIdAndJobName(id, scheduleId.toString()); return scheduleTaskMapper.entityToModel(scheduleEntityOptional .orElseThrow(() -> new NotFoundException(ResourceType.ODC_SCHEDULE_TASK, "id", id))); } From b61f0c4f70e8c07e7488fd2cbd012c969291f84f Mon Sep 17 00:00:00 2001 From: tinker Date: Mon, 1 Jul 2024 19:25:49 +0800 Subject: [PATCH 09/18] bugfix --- .../odc/service/connection/model/CloudConnectionConfig.java | 5 +++++ .../odc/service/connection/model/TestConnectionReq.java | 3 +++ 2 files changed, 8 insertions(+) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java index 88837543f0..f0c49c58d3 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java @@ -16,6 +16,11 @@ package com.oceanbase.odc.service.connection.model; public interface CloudConnectionConfig { + + String getName(); + + String getUsername(); + String getClusterName(); String getTenantName(); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java index 6b9892d455..7958d1486c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java @@ -45,6 +45,8 @@ @Data @ToString(exclude = {"password"}) public class TestConnectionReq implements CloudConnectionConfig, SSLConnectionConfig { + + private String name; /** * Connection ID,用于编辑连接页面未传密码参数时从已保存的连接信息中获取对应密码字段 */ @@ -160,6 +162,7 @@ public static TestConnectionReq fromConnection(ConnectionConfig connection, req.setPort(connection.getPort()); req.setClusterName(connection.getClusterName()); req.setDefaultSchema(connection.getDefaultSchema()); + req.setName(connection.getName()); if (accountType == ConnectionAccountType.MAIN) { req.setTenantName(connection.getTenantName()); req.setUsername(connection.getUsername()); From a34cc2f34cfdaa11884df3a3e7d94eb23435c062 Mon Sep 17 00:00:00 2001 From: tinker Date: Mon, 1 Jul 2024 22:45:19 +0800 Subject: [PATCH 10/18] rollback --- .../odc/service/connection/model/CloudConnectionConfig.java | 5 ----- .../odc/service/connection/model/TestConnectionReq.java | 3 --- 2 files changed, 8 deletions(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java index f0c49c58d3..88837543f0 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java @@ -16,11 +16,6 @@ package com.oceanbase.odc.service.connection.model; public interface CloudConnectionConfig { - - String getName(); - - String getUsername(); - String getClusterName(); String getTenantName(); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java index 7958d1486c..6b9892d455 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java @@ -45,8 +45,6 @@ @Data @ToString(exclude = {"password"}) public class TestConnectionReq implements CloudConnectionConfig, SSLConnectionConfig { - - private String name; /** * Connection ID,用于编辑连接页面未传密码参数时从已保存的连接信息中获取对应密码字段 */ @@ -162,7 +160,6 @@ public static TestConnectionReq fromConnection(ConnectionConfig connection, req.setPort(connection.getPort()); req.setClusterName(connection.getClusterName()); req.setDefaultSchema(connection.getDefaultSchema()); - req.setName(connection.getName()); if (accountType == ConnectionAccountType.MAIN) { req.setTenantName(connection.getTenantName()); req.setUsername(connection.getUsername()); From dc94e8cc034569fe53f32c50b35eb11100093a57 Mon Sep 17 00:00:00 2001 From: tinker Date: Tue, 2 Jul 2024 20:23:48 +0800 Subject: [PATCH 11/18] opt list table --- .../odc/server/web/controller/v2/DBTableController.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/DBTableController.java b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/DBTableController.java index eb81868e7b..ccd0b8089d 100644 --- a/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/DBTableController.java +++ b/server/odc-server/src/main/java/com/oceanbase/odc/server/web/controller/v2/DBTableController.java @@ -16,6 +16,7 @@ package com.oceanbase.odc.server.web.controller.v2; import java.util.Base64; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -26,6 +27,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.oceanbase.odc.common.util.StringUtils; import com.oceanbase.odc.core.session.ConnectionSession; import com.oceanbase.odc.service.common.response.ListResponse; import com.oceanbase.odc.service.common.response.Responses; @@ -59,7 +61,12 @@ public ListResponse listTables(@PathVariable String sessionId, @PathVariable(required = false) String databaseName, @RequestParam(required = false, name = "fuzzyTableName") String fuzzyTableName) { ConnectionSession session = sessionService.nullSafeGet(sessionId, true); - return Responses.list(tableService.showTablesLike(session, databaseName, fuzzyTableName)); + if (!StringUtils.isEmpty(fuzzyTableName)) { + return Responses.list(tableService.showTablesLike(session, databaseName, fuzzyTableName)); + } else { + return Responses.list(tableService.listTables(session, databaseName).stream().map(DBTable::getName).collect( + Collectors.toList())); + } } @GetMapping(value = {"/{sessionId}/databases/{databaseName}/tables/{tableName}", From 961ecc1aedf6859338610f6ee3ad6337d0e51331 Mon Sep 17 00:00:00 2001 From: tinker Date: Wed, 3 Jul 2024 09:39:57 +0800 Subject: [PATCH 12/18] bugfix --- .../odc/service/dlm/model/OffsetConfig.java | 8 +-- .../odc/service/dlm/model/Operator.java | 28 ++++++++ .../dlm/utils/DataArchiveConditionUtil.java | 65 ++++++++++++------- 3 files changed, 69 insertions(+), 32 deletions(-) create mode 100644 server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java index 03f4244b9b..3ae957f226 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/OffsetConfig.java @@ -36,11 +36,5 @@ public class OffsetConfig { private String unit; - private String value; -} - - -enum Operator { - PLUS, - MINUS + private Long value; } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java new file mode 100644 index 0000000000..3ec050838a --- /dev/null +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.oceanbase.odc.service.dlm.model; + +/** + * @Author:tinker + * @Date: 2024/7/2 21:02 + * @Descripition: + */ +public enum Operator { + PLUS, + MINUS +} + diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtil.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtil.java index 814008413d..1ee1f976b9 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtil.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtil.java @@ -29,7 +29,9 @@ import org.apache.commons.collections4.CollectionUtils; +import com.oceanbase.odc.common.util.StringUtils; import com.oceanbase.odc.service.dlm.model.OffsetConfig; +import com.oceanbase.odc.service.dlm.model.Operator; /** * @Author:tinker @@ -40,11 +42,11 @@ public class DataArchiveConditionUtil { private static final Pattern CONDITION_VARIABLES_PATTERN = Pattern.compile("\\$\\{(.+?)\\}"); public static String parseCondition(String condition, List variables, Date baseDate) { - Map variablesMap = getVariablesMap(variables); + Map variablesMap = getVariablesMap(variables); return replaceVariables(condition, variablesMap, baseDate); } - private static String replaceVariables(String condition, Map variables, Date baseDate) { + private static String replaceVariables(String condition, Map variables, Date baseDate) { Matcher matcher = CONDITION_VARIABLES_PATTERN.matcher(condition); StringBuffer sb = new StringBuffer(); while (matcher.find()) { @@ -60,55 +62,68 @@ private static String replaceVariables(String condition, Map var return sb.toString(); } - private static Map getVariablesMap(List variables) { + private static Map getVariablesMap(List variables) { if (CollectionUtils.isEmpty(variables)) { return Collections.emptyMap(); } - Map map = new HashMap<>(); + Map map = new HashMap<>(); variables.forEach(obj -> { if (map.containsKey(obj.getName())) { throw new IllegalArgumentException(String.format("Duplicate variable found,name=%s", obj.getName())); } - map.put(obj.getName(), obj.getPattern()); + map.put(obj.getName(), obj); }); return map; } - private static String calculateDateTime(Date baseDate, String pattern) { - String[] parts = pattern.split("\\|"); - String offsetString = parts[1].substring(1); - ChronoUnit unit = parseUnit(offsetString); - long offsetSeconds = parseValue(offsetString) * unit.getDuration().getSeconds(); - if (parts[1].startsWith("-")) { - offsetSeconds = -offsetSeconds; + private static String calculateDateTime(Date baseDate, OffsetConfig config) { + + LocalDateTime localDateTime; + if (StringUtils.isNotEmpty(config.getPattern())) { + String[] parts = config.getPattern().split("\\|"); + String offsetString = parts[1].substring(1); + ChronoUnit unit = parseUnit(offsetString.substring(offsetString.length() - 1)); + long offsetSeconds = parseValue(offsetString) * unit.getDuration().getSeconds(); + if (parts[1].startsWith("-")) { + offsetSeconds = -offsetSeconds; + } + localDateTime = baseDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() + .plusSeconds(offsetSeconds); + return localDateTime.format(DateTimeFormatter.ofPattern(parts[0])); + } else { + long offsetSeconds = config.getValue() * parseUnit(config.getUnit()).getDuration().getSeconds(); + if (config.getOperator() == Operator.MINUS) { + offsetSeconds = -offsetSeconds; + } + localDateTime = baseDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() + .plusSeconds(offsetSeconds); + return localDateTime.format(DateTimeFormatter.ofPattern(config.getDateFormatPattern())); } - LocalDateTime localDateTime = baseDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() - .plusSeconds(offsetSeconds); - return localDateTime.format(DateTimeFormatter.ofPattern(parts[0])); + } private static int parseValue(String offsetString) { return Integer.parseInt(offsetString.substring(0, offsetString.length() - 1)); } - private static ChronoUnit parseUnit(String offsetString) { - switch (offsetString.charAt(offsetString.length() - 1)) { - case 'y': + private static ChronoUnit parseUnit(String unit) { + switch (unit) { + case "y": return ChronoUnit.YEARS; - case 'M': + case "M": return ChronoUnit.MONTHS; - case 'd': + case "d": return ChronoUnit.DAYS; - case 'h': + case "h": return ChronoUnit.HOURS; - case 'm': + case "m": return ChronoUnit.MINUTES; - case 's': + case "s": return ChronoUnit.SECONDS; - case 'w': + case "w": return ChronoUnit.WEEKS; default: - throw new IllegalArgumentException("Unknown unit: " + offsetString); + throw new IllegalArgumentException("Unknown unit: " + unit); } } } From 56f7c851f70eb5f00f6ce755749bec1abe0b76de Mon Sep 17 00:00:00 2001 From: tinker Date: Wed, 3 Jul 2024 14:49:59 +0800 Subject: [PATCH 13/18] merge 24v2 into current branch. --- .../model/CloudConnectionConfig.java | 4 +++ .../connection/model/TestConnectionReq.java | 3 +++ .../odc/service/schedule/ScheduleService.java | 27 +++++++------------ .../service/schedule/ScheduleTaskService.java | 25 +++++++++-------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java index 88837543f0..ba3aa98380 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java @@ -15,6 +15,8 @@ */ package com.oceanbase.odc.service.connection.model; +import java.util.Map; + public interface CloudConnectionConfig { String getClusterName(); @@ -22,6 +24,8 @@ public interface CloudConnectionConfig { String getOBTenantName(); + Map getProperties(); + OBInstanceType getInstanceType(); OBInstanceRoleType getInstanceRoleType(); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java index 6b9892d455..04a2822da8 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java @@ -141,6 +141,8 @@ public class TestConnectionReq implements CloudConnectionConfig, SSLConnectionCo @JsonIgnore private OBInstanceRoleType instanceRoleType; + private Map properties; + public DialectType getDialectType() { if (Objects.nonNull(this.type)) { return this.type.getDialectType(); @@ -160,6 +162,7 @@ public static TestConnectionReq fromConnection(ConnectionConfig connection, req.setPort(connection.getPort()); req.setClusterName(connection.getClusterName()); req.setDefaultSchema(connection.getDefaultSchema()); + req.setProperties(connection.getProperties()); if (accountType == ConnectionAccountType.MAIN) { req.setTenantName(connection.getTenantName()); req.setUsername(connection.getUsername()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java index 2ac70e7ebd..c48c0be022 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java @@ -19,6 +19,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -40,8 +41,10 @@ import com.oceanbase.odc.common.json.JsonUtils; import com.oceanbase.odc.core.authority.util.SkipAuthorize; import com.oceanbase.odc.core.shared.constant.OrganizationType; +import com.oceanbase.odc.core.shared.constant.ResourceRoleName; import com.oceanbase.odc.core.shared.constant.ResourceType; import com.oceanbase.odc.core.shared.constant.TaskStatus; +import com.oceanbase.odc.core.shared.exception.AccessDeniedException; import com.oceanbase.odc.core.shared.exception.NotFoundException; import com.oceanbase.odc.core.shared.exception.UnsupportedException; import com.oceanbase.odc.metadb.collaboration.EnvironmentRepository; @@ -459,7 +462,7 @@ public List getAsyncDownloadUrl(Long id, List objectIds) { public String getLog(Long scheduleId, Long taskId, OdcTaskLogLevel logLevel) { nullSafeGetByIdWithCheckPermission(scheduleId); - return scheduleTaskService.getScheduleTaskLog(taskId, logLevel); + return scheduleTaskService.getLogWithoutPermission(taskId, logLevel); } public Schedule nullSafeGetByIdWithCheckPermission(Long id) { @@ -468,23 +471,11 @@ public Schedule nullSafeGetByIdWithCheckPermission(Long id) { public Schedule nullSafeGetByIdWithCheckPermission(Long id, boolean isWrite) { Schedule schedule = nullSafeGetModelById(id); - // Long projectId = schedule.getProjectId(); - // if (isWrite) { - // List resourceRoleNames = getApproverRoleNames(Schedule); - // if (resourceRoleNames.isEmpty()) { - // resourceRoleNames = ResourceRoleName.all(); - // } - // if ((Objects.nonNull(projectId) - // && !projectPermissionValidator.hasProjectRole(projectId, resourceRoleNames))) { - // throw new AccessDeniedException(); - // } - // } else { - // - // if (Objects.nonNull(projectId) - // && !projectPermissionValidator.hasProjectRole(projectId, ResourceRoleName.all())) { - // throw new AccessDeniedException(); - // } - // } + Long projectId = schedule.getProjectId(); + if ((Objects.nonNull(projectId) + && !projectPermissionValidator.hasProjectRole(projectId, ResourceRoleName.all()))) { + throw new AccessDeniedException(); + } return schedule; } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java index 7de1a42f17..64bd97f564 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java @@ -52,7 +52,6 @@ import com.oceanbase.odc.service.dispatch.RequestDispatcher; import com.oceanbase.odc.service.dispatch.TaskDispatchChecker; import com.oceanbase.odc.service.dlm.DLMService; -import com.oceanbase.odc.service.logger.LoggerService; import com.oceanbase.odc.service.quartz.QuartzJobService; import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; @@ -67,6 +66,7 @@ import com.oceanbase.odc.service.schedule.model.ScheduleTaskType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; import com.oceanbase.odc.service.schedule.model.TriggerStrategy; +import com.oceanbase.odc.service.task.TaskLoggerService; import com.oceanbase.odc.service.task.config.TaskFrameworkEnabledProperties; import com.oceanbase.odc.service.task.exception.JobException; import com.oceanbase.odc.service.task.model.ExecutorInfo; @@ -108,7 +108,7 @@ public class ScheduleTaskService { private RequestDispatcher requestDispatcher; @Autowired - private LoggerService loggerService; + private TaskLoggerService taskLoggerService; private final ScheduleTaskMapper scheduleTaskMapper = ScheduleTaskMapper.INSTANCE; @@ -262,32 +262,35 @@ public ScheduleTask nullSafeGetByIdAndScheduleId(Long id, Long scheduleId) { .orElseThrow(() -> new NotFoundException(ResourceType.ODC_SCHEDULE_TASK, "id", id))); } - public String getScheduleTaskLog(Long id, OdcTaskLogLevel logLevel) { - ScheduleTask scheduleTask = nullSafeGetModelById(id); - - if (taskFrameworkEnabledProperties.isEnabled() && scheduleTask.getJobId() != null) { + public String getLogWithoutPermission(Long taskId, OdcTaskLogLevel logLevel) { + ScheduleTaskEntity taskEntity = nullSafeGetById(taskId); + if (taskFrameworkEnabledProperties.isEnabled() && taskEntity.getJobId() != null) { try { - return loggerService.getLogByTaskFramework(logLevel, scheduleTask.getJobId()); + return taskLoggerService.getLogByTaskFramework(logLevel, taskEntity.getJobId()); } catch (IOException e) { log.warn("Copy input stream to file failed.", e); throw new UnexpectedException("Copy input stream to file failed."); } } - ExecutorInfo executorInfo = JsonUtils.fromJson(scheduleTask.getExecutor(), ExecutorInfo.class); + ExecutorInfo executorInfo = JsonUtils.fromJson(taskEntity.getExecutor(), ExecutorInfo.class); if (!dispatchChecker.isThisMachine(executorInfo)) { try { DispatchResponse response = requestDispatcher.forward(executorInfo.getHost(), executorInfo.getPort()); - log.info("Remote get task log succeed,taskId={}", id); + log.info("Remote get task log succeed,taskId={}", taskId); return response.getContentByType( new TypeReference>() {}).getData(); } catch (Exception e) { - log.warn("Remote get task log failed, taskId={}", id, e); - throw new UnexpectedException(String.format("Remote interrupt task failed, taskId=%s", id)); + log.warn("Remote get task log failed, taskId={}", taskId, e); + throw new UnexpectedException(String.format("Remote interrupt task failed, taskId=%s", taskId)); } } + return getScheduleTaskLog(taskId, logLevel); + } + public String getScheduleTaskLog(Long id, OdcTaskLogLevel logLevel) { + ScheduleTask scheduleTask = nullSafeGetModelById(id); String filePath = String.format(LOG_PATH_PATTERN, logDirectory, scheduleTask.getJobName(), scheduleTask.getJobGroup(), id, logLevel.name().toLowerCase()); From 6e2688d58291332bb81ec0c13ebd3e089ec841d2 Mon Sep 17 00:00:00 2001 From: tinker Date: Wed, 3 Jul 2024 15:07:04 +0800 Subject: [PATCH 14/18] code format --- .../java/com/oceanbase/odc/service/dlm/model/Operator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java index 3ec050838a..4e1fecf164 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/dlm/model/Operator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 OceanBase. + * Copyright (c) 2023 OceanBase. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.oceanbase.odc.service.dlm.model; /** From 381a91e8fdf725e66cd02cce0bcec015c0b3d712 Mon Sep 17 00:00:00 2001 From: tinker Date: Wed, 3 Jul 2024 17:54:08 +0800 Subject: [PATCH 15/18] code format --- .../odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java | 2 +- .../odc/service/onlineschemachange/BaseOscTestEnv.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java index 091f7dbadc..3683fb264e 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/metadb/schedule/ScheduleChangeLogRepositoryTest.java @@ -23,7 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import com.oceanbase.odc.ServiceTestEnv; -import com.oceanbase.odc.service.schedule.flowtask.OperationType; +import com.oceanbase.odc.service.schedule.model.OperationType; import com.oceanbase.odc.service.schedule.model.ScheduleChangeStatus; /** diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java index 217900b297..c14c2eae2a 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/BaseOscTestEnv.java @@ -180,7 +180,7 @@ protected ScheduleEntity getScheduleEntity(ConnectionConfig config, OnlineSchema scheduleEntity.setStatus(ScheduleStatus.ENABLED); scheduleEntity.setAllowConcurrent(false); scheduleEntity.setMisfireStrategy(MisfireStrategy.MISFIRE_INSTRUCTION_DO_NOTHING); - scheduleEntity.setScheduleType(ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE); + scheduleEntity.setType(ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE); scheduleEntity.setJobParametersJson(JsonUtils.toJson(changeParameters)); TriggerConfig triggerConfig = new TriggerConfig(); triggerConfig.setTriggerStrategy(TriggerStrategy.CRON); From bba46806cd5ad67b29a6691908821cc12b1f55b6 Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 4 Jul 2024 16:41:58 +0800 Subject: [PATCH 16/18] response comment --- .../odc/quartz/QuartzJobServiceTest.java | 4 ++-- .../model/CloudConnectionConfig.java | 2 +- .../connection/model/TestConnectionReq.java | 4 ++-- .../odc/service/quartz/QuartzJobService.java | 12 +++++----- .../util/QuartzCronExpressionUtils.java | 11 +++++++++ .../odc/service/schedule/ScheduleService.java | 23 +++++++++++------- .../service/schedule/ScheduleTaskService.java | 6 ++--- .../ScheduleResponseMapperFactory.java | 2 +- ...hangeReq.java => ChangeQuartJobParam.java} | 2 +- ...zJobReq.java => CreateQuartzJobParam.java} | 2 +- .../schedule/model/CreateScheduleReq.java | 4 ++-- .../schedule/model/ScheduleChangeLog.java | 8 +++---- .../processor/DataArchivePreprocessor.java | 2 ++ .../processor/DataDeletePreprocessor.java | 2 ++ ...t.java => ScheduleChangePreprocessor.java} | 24 ++++++------------- .../utils/DataArchiveConditionUtilTest.java | 6 ++++- 16 files changed, 64 insertions(+), 50 deletions(-) rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/{QuartzJobChangeReq.java => ChangeQuartJobParam.java} (97%) rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/{CreateQuartzJobReq.java => CreateQuartzJobParam.java} (97%) rename server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/{CreateScheduleAspect.java => ScheduleChangePreprocessor.java} (81%) diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java index b4bb0f3489..f47b185917 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/quartz/QuartzJobServiceTest.java @@ -27,7 +27,7 @@ import com.oceanbase.odc.ServiceTestEnv; import com.oceanbase.odc.service.quartz.QuartzJobService; -import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; +import com.oceanbase.odc.service.schedule.model.CreateQuartzJobParam; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; @@ -45,7 +45,7 @@ public class QuartzJobServiceTest extends ServiceTestEnv { @Test public void create() throws SchedulerException, ParseException { - CreateQuartzJobReq req = new CreateQuartzJobReq(); + CreateQuartzJobParam req = new CreateQuartzJobParam(); req.setJobKey(QuartzKeyGenerator.generateJobKey("1", ScheduleType.SQL_PLAN.name())); TriggerConfig config = new TriggerConfig(); config.setTriggerStrategy(TriggerStrategy.START_AT); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java index ba3aa98380..ac1d59cb7a 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/CloudConnectionConfig.java @@ -24,7 +24,7 @@ public interface CloudConnectionConfig { String getOBTenantName(); - Map getProperties(); + Map getAttributes(); OBInstanceType getInstanceType(); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java index 04a2822da8..d201e81b3b 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/TestConnectionReq.java @@ -141,7 +141,7 @@ public class TestConnectionReq implements CloudConnectionConfig, SSLConnectionCo @JsonIgnore private OBInstanceRoleType instanceRoleType; - private Map properties; + private Map attributes; public DialectType getDialectType() { if (Objects.nonNull(this.type)) { @@ -162,7 +162,7 @@ public static TestConnectionReq fromConnection(ConnectionConfig connection, req.setPort(connection.getPort()); req.setClusterName(connection.getClusterName()); req.setDefaultSchema(connection.getDefaultSchema()); - req.setProperties(connection.getProperties()); + req.setAttributes(connection.getAttributes()); if (accountType == ConnectionAccountType.MAIN) { req.setTenantName(connection.getTenantName()); req.setUsername(connection.getUsername()); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java index fb6d7d0f6c..3e9d599484 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/QuartzJobService.java @@ -42,8 +42,8 @@ import com.oceanbase.odc.service.quartz.executor.QuartzJob; import com.oceanbase.odc.service.quartz.model.MisfireStrategy; import com.oceanbase.odc.service.quartz.util.QuartzCronExpressionUtils; -import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; -import com.oceanbase.odc.service.schedule.model.QuartzJobChangeReq; +import com.oceanbase.odc.service.schedule.model.ChangeQuartJobParam; +import com.oceanbase.odc.service.schedule.model.CreateQuartzJobParam; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.TriggerConfig; @@ -61,13 +61,13 @@ public class QuartzJobService { @Qualifier(value = ("defaultScheduler")) private Scheduler scheduler; - public void changeQuartzJob(QuartzJobChangeReq req) { + public void changeQuartzJob(ChangeQuartJobParam req) { JobKey jobKey = QuartzKeyGenerator.generateJobKey(req.getJobName(), req.getJobGroup()); try { switch (req.getOperationType()) { case CREATE: { - CreateQuartzJobReq createQuartzJobReq = new CreateQuartzJobReq(); + CreateQuartzJobParam createQuartzJobReq = new CreateQuartzJobParam(); createQuartzJobReq.setJobKey(jobKey); createQuartzJobReq.setAllowConcurrent(req.getAllowConcurrent()); createQuartzJobReq.setMisfireStrategy(req.getMisfireStrategy()); @@ -100,12 +100,12 @@ public void changeQuartzJob(QuartzJobChangeReq req) { } - public void createJob(CreateQuartzJobReq req) throws SchedulerException { + public void createJob(CreateQuartzJobParam req) throws SchedulerException { createJob(req, null); } // TODO how can we recognize multi trigger for job. maybe we can use jobName as trigger group. - public void createJob(CreateQuartzJobReq req, JobDataMap triggerDataMap) throws SchedulerException { + public void createJob(CreateQuartzJobParam req, JobDataMap triggerDataMap) throws SchedulerException { Class clazz = QuartzJob.class; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java index 0d24d97f85..58fadeb8b5 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java @@ -26,6 +26,9 @@ import org.quartz.CronExpression; +import com.oceanbase.odc.service.schedule.model.TriggerConfig; +import com.oceanbase.odc.service.schedule.model.TriggerStrategy; + /** * @Author:tinker * @Date: 2023/1/4 16:00 @@ -106,6 +109,14 @@ private static String adaptDayOfWeek(String dayOfWeek) throws ParseException { return sb.toString(); } + public static List getNextFiveFireTimes(TriggerConfig triggerConfig) { + if (triggerConfig.getTriggerStrategy() == TriggerStrategy.CRON + || triggerConfig.getTriggerStrategy() == TriggerStrategy.START_AT) { + return Collections.emptyList(); + } + return getNextFiveFireTimes(triggerConfig.getCronExpression()); + } + public static List getNextFiveFireTimes(String cronExpression) { return getNextFiveFireTimes(cronExpression, 5); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java index c48c0be022..d8cbadae75 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleService.java @@ -53,7 +53,6 @@ import com.oceanbase.odc.metadb.schedule.ScheduleRepository; import com.oceanbase.odc.service.collaboration.project.ProjectService; import com.oceanbase.odc.service.connection.database.DatabaseService; -import com.oceanbase.odc.service.flow.processor.EnablePreprocess; import com.oceanbase.odc.service.iam.OrganizationService; import com.oceanbase.odc.service.iam.ProjectPermissionValidator; import com.oceanbase.odc.service.iam.auth.AuthenticationFacade; @@ -63,14 +62,15 @@ import com.oceanbase.odc.service.quartz.model.MisfireStrategy; import com.oceanbase.odc.service.regulation.approval.ApprovalFlowConfigSelector; import com.oceanbase.odc.service.schedule.factory.ScheduleResponseMapperFactory; -import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; +import com.oceanbase.odc.service.schedule.model.ChangeQuartJobParam; +import com.oceanbase.odc.service.schedule.model.CreateQuartzJobParam; import com.oceanbase.odc.service.schedule.model.OperationType; -import com.oceanbase.odc.service.schedule.model.QuartzJobChangeReq; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; import com.oceanbase.odc.service.schedule.model.QueryScheduleParams; import com.oceanbase.odc.service.schedule.model.Schedule; import com.oceanbase.odc.service.schedule.model.ScheduleChangeLog; import com.oceanbase.odc.service.schedule.model.ScheduleChangeParams; +import com.oceanbase.odc.service.schedule.model.ScheduleChangeStatus; import com.oceanbase.odc.service.schedule.model.ScheduleDetailResp; import com.oceanbase.odc.service.schedule.model.ScheduleMapper; import com.oceanbase.odc.service.schedule.model.ScheduleOverview; @@ -79,6 +79,7 @@ import com.oceanbase.odc.service.schedule.model.ScheduleTaskOverview; import com.oceanbase.odc.service.schedule.model.ScheduleType; import com.oceanbase.odc.service.schedule.model.TriggerConfig; +import com.oceanbase.odc.service.schedule.processor.ScheduleChangePreprocessor; import com.oceanbase.odc.service.task.model.OdcTaskLogLevel; import lombok.extern.slf4j.Slf4j; @@ -133,20 +134,23 @@ public class ScheduleService { @Autowired private OrganizationService organizationService; + @Autowired + private ScheduleChangePreprocessor preprocessor; + private final ScheduleMapper scheduleMapper = ScheduleMapper.INSTANCE; - @EnablePreprocess @Transactional(rollbackFor = Exception.class) public Schedule changeSchedule(ScheduleChangeParams req) { + preprocessor.process(req); Schedule targetSchedule; // create or load target schedule if (req.getOperationType() == OperationType.CREATE) { ScheduleEntity entity = new ScheduleEntity(); - entity.setProjectId(1L); + entity.setProjectId(req.getCreateScheduleReq().getProjectId()); entity.setDescription(req.getCreateScheduleReq().getDescription()); entity.setJobParametersJson(JsonUtils.toJson(req.getCreateScheduleReq().getParameters())); entity.setTriggerConfigJson(JsonUtils.toJson(req.getCreateScheduleReq().getTriggerConfig())); @@ -186,7 +190,8 @@ public Schedule changeSchedule(ScheduleChangeParams req) { req.getOperationType() == OperationType.UPDATE ? JsonUtils.toJson(req.getUpdateScheduleReq().getParameters()) : null, - approvalFlowInstanceId)); + approvalFlowInstanceId, approvalFlowInstanceId == null ? ScheduleChangeStatus.SUCCESS + : ScheduleChangeStatus.APPROVING)); log.info("Create change log success,changLog={}", changeLog); return targetSchedule; } @@ -219,7 +224,7 @@ public void executeChangeSchedule(ScheduleChangeParams req) { } // start change quartzJob - QuartzJobChangeReq quartzJobReq = new QuartzJobChangeReq(); + ChangeQuartJobParam quartzJobReq = new ChangeQuartJobParam(); quartzJobReq.setOperationType(req.getOperationType()); quartzJobReq.setJobName(targetSchedule.getId().toString()); quartzJobReq.setJobGroup(targetSchedule.getType().name()); @@ -497,8 +502,8 @@ private Trigger nullSafeGetScheduleTrigger(ScheduleEntity schedule) throws Sched return trigger; } - private CreateQuartzJobReq buildCreateJobReq(ScheduleEntity schedule) { - CreateQuartzJobReq createQuartzJobReq = new CreateQuartzJobReq(); + private CreateQuartzJobParam buildCreateJobReq(ScheduleEntity schedule) { + CreateQuartzJobParam createQuartzJobReq = new CreateQuartzJobParam(); createQuartzJobReq.setJobKey(QuartzKeyGenerator.generateJobKey(schedule)); createQuartzJobReq.setTriggerConfig(JsonUtils.fromJson(schedule.getTriggerConfigJson(), TriggerConfig.class)); if (schedule.getType() == ScheduleType.ONLINE_SCHEMA_CHANGE_COMPLETE) { diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java index 64bd97f564..2929f37a2c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/ScheduleTaskService.java @@ -54,7 +54,7 @@ import com.oceanbase.odc.service.dlm.DLMService; import com.oceanbase.odc.service.quartz.QuartzJobService; import com.oceanbase.odc.service.quartz.util.ScheduleTaskUtils; -import com.oceanbase.odc.service.schedule.model.CreateQuartzJobReq; +import com.oceanbase.odc.service.schedule.model.CreateQuartzJobParam; import com.oceanbase.odc.service.schedule.model.DataArchiveClearParameters; import com.oceanbase.odc.service.schedule.model.DataArchiveRollbackParameters; import com.oceanbase.odc.service.schedule.model.QuartzKeyGenerator; @@ -359,7 +359,7 @@ public void triggerDataArchiveDelete(Long scheduleTaskId) { log.info("Data archive delete job exists and start delete job,jobKey={}", jobKey); quartzJobService.deleteJob(jobKey); } - CreateQuartzJobReq req = new CreateQuartzJobReq(); + CreateQuartzJobParam req = new CreateQuartzJobParam(); req.setJobKey(jobKey); DataArchiveClearParameters parameters = new DataArchiveClearParameters(); parameters.setDataArchiveTaskId(scheduleTaskId); @@ -393,7 +393,7 @@ public void rollbackTask(Long scheduleTaskId) { log.info("Data archive rollback job exists and start delete job,jobKey={}", jobKey); quartzJobService.deleteJob(jobKey); } - CreateQuartzJobReq req = new CreateQuartzJobReq(); + CreateQuartzJobParam req = new CreateQuartzJobParam(); req.setJobKey(jobKey); DataArchiveRollbackParameters parameters = new DataArchiveRollbackParameters(); parameters.setDataArchiveTaskId(scheduleTaskId); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java index 86f8c1b878..a7781e7ce5 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/factory/ScheduleResponseMapperFactory.java @@ -96,7 +96,7 @@ public ScheduleDetailResp generateScheduleDetailResp(@NonNull Schedule schedule) scheduleDetailResp.setDescription(schedule.getDescription()); scheduleDetailResp.setNextFireTimes( - QuartzCronExpressionUtils.getNextFiveFireTimes(schedule.getTriggerConfig().getCronExpression())); + QuartzCronExpressionUtils.getNextFiveFireTimes(schedule.getTriggerConfig())); userRepository.findById(schedule.getCreatorId()) .ifPresent(o -> scheduleDetailResp.setCreator(new InnerUser(o, null))); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ChangeQuartJobParam.java similarity index 97% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ChangeQuartJobParam.java index fe837bc654..4e529c7d6c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/QuartzJobChangeReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ChangeQuartJobParam.java @@ -28,7 +28,7 @@ */ @Data -public class QuartzJobChangeReq { +public class ChangeQuartJobParam { private String jobName; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobParam.java similarity index 97% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobParam.java index b7dba239f3..eaca55610f 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateQuartzJobParam.java @@ -29,7 +29,7 @@ */ @Data -public class CreateQuartzJobReq { +public class CreateQuartzJobParam { private JobKey jobKey; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java index 9cc3be1989..acc9287bb7 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/CreateScheduleReq.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.oceanbase.odc.service.dlm.model.DataArchiveParameters; import com.oceanbase.odc.service.dlm.model.DataDeleteParameters; +import com.oceanbase.odc.service.schedule.processor.ScheduleChangePreprocessor; import lombok.Data; @@ -52,8 +53,7 @@ public class CreateScheduleReq { private String description; /** - * Followings are filled by aspect - * {@link com.oceanbase.odc.service.schedule.processor.CreateScheduleAspect} + * Followings are filled by aspect {@link ScheduleChangePreprocessor} */ @JsonProperty(access = Access.READ_ONLY) private Long projectId; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java index 732ef3694b..8cf222c7d6 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/model/ScheduleChangeLog.java @@ -47,16 +47,16 @@ public class ScheduleChangeLog { private Date updateTime; public static ScheduleChangeLog build(Long scheduleId, OperationType type, String oldParameters, - String newParameters) { + String newParameters, ScheduleChangeStatus status) { - return build(scheduleId, type, oldParameters, newParameters, null); + return build(scheduleId, type, oldParameters, newParameters, null, status); } public static ScheduleChangeLog build(Long scheduleId, OperationType type, String oldParameters, - String newParameters, Long flowInstanceId) { + String newParameters, Long flowInstanceId, ScheduleChangeStatus status) { ScheduleChangeLog log = new ScheduleChangeLog(); log.setScheduleId(scheduleId); - log.setStatus(ScheduleChangeStatus.SUCCESS); + log.setStatus(status); log.setType(type); log.setOldScheduleParameterJson(oldParameters); log.setNewScheduleParameterJson(newParameters); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java index 6cc1ac42c1..885acb7df9 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataArchivePreprocessor.java @@ -71,6 +71,8 @@ public void process(ScheduleChangeParams req) { // permission to access it. Database sourceDb = databaseService.detail(parameters.getSourceDatabaseId()); Database targetDb = databaseService.detail(parameters.getTargetDataBaseId()); + parameters.setSourceDatabase(sourceDb); + parameters.setTargetDatabase(targetDb); if (!parameters.getSyncTableStructure().isEmpty() && sourceDb.getDataSource().getDialectType() != targetDb.getDataSource().getDialectType()) { throw new UnsupportedException( diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java index d3a7f69c33..f0d4e9b5f6 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/DataDeletePreprocessor.java @@ -71,8 +71,10 @@ public void process(ScheduleChangeParams req) { throw new IllegalArgumentException("target database id can not be null"); } Database targetDb = databaseService.detail(parameters.getTargetDatabaseId()); + parameters.setTargetDatabase(targetDb); } Database sourceDb = databaseService.detail(parameters.getDatabaseId()); + parameters.setDatabase(sourceDb); ConnectionConfig dataSource = sourceDb.getDataSource(); dataSource.setDefaultSchema(sourceDb.getName()); ConnectionSessionFactory connectionSessionFactory = new DefaultConnectSessionFactory(dataSource); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleChangePreprocessor.java similarity index 81% rename from server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java rename to server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleChangePreprocessor.java index 88b3a75cdf..c8b2c3be0c 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/CreateScheduleAspect.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/schedule/processor/ScheduleChangePreprocessor.java @@ -19,10 +19,7 @@ import java.util.List; import java.util.Map; -import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -49,7 +46,7 @@ @Slf4j @Aspect @Component -public class CreateScheduleAspect implements InitializingBean { +public class ScheduleChangePreprocessor implements InitializingBean { @Autowired private DatabaseService databaseService; @Autowired @@ -59,24 +56,17 @@ public class CreateScheduleAspect implements InitializingBean { private final Map type2Processor = new HashMap<>(); - - @Pointcut("@annotation(com.oceanbase.odc.service.flow.processor.EnablePreprocess) && args(com.oceanbase.odc.service.schedule.model.ScheduleChangeParams)") - public void processBeforeChangeSchedule() {} - - - @Before("processBeforeChangeSchedule()") - public void createPreprocess(JoinPoint point) throws Throwable { - ScheduleChangeParams req = (ScheduleChangeParams) point.getArgs()[0]; + public void process(ScheduleChangeParams params) { ScheduleType type; - if (req.getOperationType() == OperationType.CREATE) { - type = req.getCreateScheduleReq().getType(); - adaptCreateScheduleReq(req.getCreateScheduleReq()); + if (params.getOperationType() == OperationType.CREATE) { + type = params.getCreateScheduleReq().getType(); + adaptCreateScheduleReq(params.getCreateScheduleReq()); } else { - type = scheduleService.nullSafeGetModelById(req.getScheduleId()).getType(); + type = scheduleService.nullSafeGetModelById(params.getScheduleId()).getType(); } if (type2Processor.containsKey(type)) { - type2Processor.get(type).process(req); + type2Processor.get(type).process(params); } } diff --git a/server/odc-service/src/test/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtilTest.java b/server/odc-service/src/test/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtilTest.java index 4886bc1a64..6c8dd523f7 100644 --- a/server/odc-service/src/test/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtilTest.java +++ b/server/odc-service/src/test/java/com/oceanbase/odc/service/dlm/utils/DataArchiveConditionUtilTest.java @@ -26,6 +26,7 @@ import org.junit.rules.ExpectedException; import com.oceanbase.odc.service.dlm.model.OffsetConfig; +import com.oceanbase.odc.service.dlm.model.Operator; import cn.hutool.core.lang.Assert; @@ -48,7 +49,10 @@ public void testParseCondition() { config.setPattern("yyyy-MM-dd HH:mm:ss|+10m"); OffsetConfig config2 = new OffsetConfig(); config2.setName("end"); - config2.setPattern("yyyy-MM-dd|+1d"); + config2.setOperator(Operator.PLUS); + config2.setDateFormatPattern("yyyy-MM-dd"); + config2.setUnit("d"); + config2.setValue(1L); List variables = new LinkedList<>(); variables.add(config); variables.add(config2); From 3420ad386a05460528c64a12001b13c705284afb Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 4 Jul 2024 17:22:11 +0800 Subject: [PATCH 17/18] fix ut --- .../service/partitionplan/PartitionPlanScheduleService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java index d11091cc98..71f0a16274 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/partitionplan/PartitionPlanScheduleService.java @@ -267,8 +267,8 @@ private ScheduleEntity createAndEnableSchedule(Database database, @NonNull Trigg scheduleEntity.setCreatorId(this.authenticationFacade.currentUserId()); scheduleEntity.setModifierId(this.authenticationFacade.currentUserId()); scheduleEntity.setOrganizationId(this.authenticationFacade.currentOrganizationId()); - // scheduleEntity = this.scheduleService.create(scheduleEntity); - // this.scheduleService.enable(scheduleEntity); + scheduleEntity = this.scheduleService.create(scheduleEntity); + this.scheduleService.enable(scheduleEntity); return scheduleEntity; } From f23bbc2346cbfb55a2e1f37be375c96ee6c84cb0 Mon Sep 17 00:00:00 2001 From: tinker Date: Thu, 4 Jul 2024 18:17:31 +0800 Subject: [PATCH 18/18] bugfix --- .../odc/service/quartz/util/QuartzCronExpressionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java index 58fadeb8b5..c9e35726ca 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/quartz/util/QuartzCronExpressionUtils.java @@ -110,7 +110,7 @@ private static String adaptDayOfWeek(String dayOfWeek) throws ParseException { } public static List getNextFiveFireTimes(TriggerConfig triggerConfig) { - if (triggerConfig.getTriggerStrategy() == TriggerStrategy.CRON + if (triggerConfig.getTriggerStrategy() == TriggerStrategy.START_NOW || triggerConfig.getTriggerStrategy() == TriggerStrategy.START_AT) { return Collections.emptyList(); }