diff --git a/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/JobExecutorResultActor.java b/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/JobExecutorResultActor.java index dfb07dcc2..49a7e9b86 100644 --- a/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/JobExecutorResultActor.java +++ b/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/JobExecutorResultActor.java @@ -80,20 +80,6 @@ public class JobExecutorResultActor extends AbstractActor { } }); - // TODO 60秒内的任务直接丢入时间轮中 - if (Integer.parseInt("30") <= 60) { - if (jobTaskBatchMapper.selectCount(new LambdaQueryWrapper() - .eq(JobTaskBatch::getId, result.getTaskBatchId()) - .in(JobTaskBatch::getTaskStatus, JobTaskBatchStatusEnum.NOT_COMPLETE)) <= 0) { - ActorRef scanActorRef = CacheGroupScanActor.get("DEFAULT_JOB_KEY", TaskTypeEnum.JOB); - ScanTask scanTask = new ScanTask(); - scanTask.setBuckets(Sets.newHashSet(0)); - scanTask.setSize(1); - scanTask.setStartId(result.getJobId()); - scanActorRef.tell(scanTask, scanActorRef); - } - } - JobLogDTO jobLogDTO = JobTaskConverter.INSTANCE.toJobLogDTO(result); jobLogDTO.setMessage(result.getMessage()); jobLogDTO.setClientId(result.getClientId()); diff --git a/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/ScanJobTaskActor.java b/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/ScanJobTaskActor.java index 0cc7374e1..0d916c2da 100644 --- a/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/ScanJobTaskActor.java +++ b/easy-retry-server/easy-retry-server-job-task/src/main/java/com/aizuda/easy/retry/server/job/task/dispatch/ScanJobTaskActor.java @@ -52,8 +52,6 @@ public class ScanJobTaskActor extends AbstractActor { @Autowired private JobMapper jobMapper; - private static final AtomicLong lastId = new AtomicLong(0L); - @Override public Receive createReceive() { return receiveBuilder().match(ScanTask.class, config -> { @@ -104,9 +102,9 @@ public class ScanJobTaskActor extends AbstractActor { new LambdaQueryWrapper() .eq(Job::getJobStatus, StatusEnum.YES.getStatus()) .in(Job::getBucketIndex, scanTask.getBuckets()) - .le(Job::getNextTriggerAt, LocalDateTime.now().plusSeconds(60)) + .le(Job::getNextTriggerAt, LocalDateTime.now().plusSeconds(10)) .eq(Job::getDeleted, StatusEnum.NO.getStatus()) - .gt(Job::getId, startId) + .ge(Job::getId, startId) ).getRecords(); return JobTaskConverter.INSTANCE.toJobPartitionTasks(jobs); diff --git a/easy-retry-server/easy-retry-server-starter/src/main/java/com/aizuda/easy/retry/server/dispatch/DispatchService.java b/easy-retry-server/easy-retry-server-starter/src/main/java/com/aizuda/easy/retry/server/dispatch/DispatchService.java index b37bad134..0ba4746c0 100644 --- a/easy-retry-server/easy-retry-server-starter/src/main/java/com/aizuda/easy/retry/server/dispatch/DispatchService.java +++ b/easy-retry-server/easy-retry-server-starter/src/main/java/com/aizuda/easy/retry/server/dispatch/DispatchService.java @@ -35,7 +35,7 @@ public class DispatchService implements Lifecycle { /** * 调度时长 */ - public static final Long PERIOD = 60L; + public static final Long PERIOD = 10L; /** * 延迟10s为了尽可能保障集群节点都启动完成在进行rebalance diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/JobController.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/JobController.java new file mode 100644 index 000000000..bf8728e88 --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/JobController.java @@ -0,0 +1,51 @@ +package com.aizuda.easy.retry.server.web.controller; + +import com.aizuda.easy.retry.server.web.annotation.LoginRequired; +import com.aizuda.easy.retry.server.web.model.base.PageResult; +import com.aizuda.easy.retry.server.web.model.request.JobQueryVO; +import com.aizuda.easy.retry.server.web.model.request.JobRequestVO; +import com.aizuda.easy.retry.server.web.model.response.JobResponseVO; +import com.aizuda.easy.retry.server.web.model.response.SceneConfigResponseVO; +import com.aizuda.easy.retry.server.web.service.JobService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:18:29 + * @since 2.4.0 + */ +@RestController +@RequestMapping("/job") +public class JobController { + + @Autowired + private JobService jobService; + + @GetMapping("/list") + @LoginRequired + public PageResult> getJobPage(JobQueryVO jobQueryVO) { + return jobService.getJobPage(jobQueryVO); + } + + @GetMapping("{id}") + @LoginRequired + public PageResult> getJobDetail(@PathVariable("id") Long id) { + return jobService.getJobDetail(id); + } + + @PostMapping + @LoginRequired + public PageResult> saveJob(@RequestBody JobRequestVO jobRequestVO) { + return jobService.saveJob(jobRequestVO); + } + + @PutMapping + @LoginRequired + public PageResult> updateJob(@RequestBody JobRequestVO jobRequestVO) { + return jobService.updateJob(jobRequestVO); + } + +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/interceptor/XRetryWebMvcConfigurerAdapter.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/interceptor/EasyRetryRetryWebMvcConfigurerAdapter.java similarity index 94% rename from easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/interceptor/XRetryWebMvcConfigurerAdapter.java rename to easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/interceptor/EasyRetryRetryWebMvcConfigurerAdapter.java index 4e92b7806..0b3811667 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/interceptor/XRetryWebMvcConfigurerAdapter.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/interceptor/EasyRetryRetryWebMvcConfigurerAdapter.java @@ -15,7 +15,7 @@ import java.util.List; * @since 2.0 */ @Configuration -public class XRetryWebMvcConfigurerAdapter implements WebMvcConfigurer { +public class EasyRetryRetryWebMvcConfigurerAdapter implements WebMvcConfigurer { @Autowired private LoginUserMethodArgumentResolver loginUserMethodArgumentResolver; diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/JobQueryVO.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/JobQueryVO.java new file mode 100644 index 000000000..a38dda1ee --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/JobQueryVO.java @@ -0,0 +1,11 @@ +package com.aizuda.easy.retry.server.web.model.request; + +import com.aizuda.easy.retry.server.web.model.base.BaseQueryVO; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:28:07 + * @since 2.4.0 + */ +public class JobQueryVO extends BaseQueryVO { +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/JobRequestVO.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/JobRequestVO.java new file mode 100644 index 000000000..a4fe6194d --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/JobRequestVO.java @@ -0,0 +1,12 @@ +package com.aizuda.easy.retry.server.web.model.request; + +import lombok.Data; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:37:55 + * @since 2.4.0 + */ +@Data +public class JobRequestVO { +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/JobResponseVO.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/JobResponseVO.java new file mode 100644 index 000000000..2d77ec82b --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/JobResponseVO.java @@ -0,0 +1,132 @@ +package com.aizuda.easy.retry.server.web.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:30:00 + * @since 2.4.0 + */ +@Data +public class JobResponseVO { + + private Long id; + + /** + * 组名称 + */ + private String groupName; + + /** + * 名称 + */ + private String jobName; + + /** + * 执行方法参数 + */ + private String argsStr; + + /** + * 参数类型 text/json + */ + private String argsType; + + /** + * 扩展字段 + */ + private String extAttrs; + + /** + * 下次触发时间 + */ + private LocalDateTime nextTriggerAt; + + /** + * 重试状态 0、关闭、1、开启 + */ + private Integer jobStatus; + + /** + * 执行器路由策略 + */ + private String routeKey; + + /** + * 执行器类型 1、Java + */ + private Integer executorType; + + /** + * 执行器名称 + */ + private String executorName; + + /** + * 触发类型 1.CRON 表达式 2. 固定时间 + */ + private Integer triggerType; + + /** + * 间隔时长 + */ + private String triggerInterval; + + /** + * 阻塞策略 1、丢弃 2、覆盖 3、并行 + */ + private Integer blockStrategy; + + /** + * 任务执行超时时间,单位秒 + */ + private Integer executorTimeout; + + /** + * 最大重试次数 + */ + private Integer maxRetryTimes; + + /** + * 重试间隔(s) + */ + private Integer retryInterval; + + /** + * 任务类型 + */ + private Integer taskType; + + /** + * 并行数 + */ + private Integer parallelNum; + + /** + * bucket + */ + private Integer bucketIndex; + + /** + * 描述 + */ + private String description; + + /** + * 创建时间 + */ + private LocalDateTime createDt; + + /** + * 修改时间 + */ + private LocalDateTime updateDt; + + /** + * 逻辑删除 1、删除 + */ + private Integer deleted; + +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/JobService.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/JobService.java new file mode 100644 index 000000000..47d3e90d9 --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/JobService.java @@ -0,0 +1,24 @@ +package com.aizuda.easy.retry.server.web.service; + +import com.aizuda.easy.retry.server.web.model.base.PageResult; +import com.aizuda.easy.retry.server.web.model.request.JobQueryVO; +import com.aizuda.easy.retry.server.web.model.request.JobRequestVO; +import com.aizuda.easy.retry.server.web.model.response.JobResponseVO; + +import java.util.List; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:20:23 + * @since 2.4.0 + */ +public interface JobService { + PageResult> getJobPage(JobQueryVO jobQueryVO); + + PageResult> getJobDetail(Long id); + + PageResult> saveJob(JobRequestVO jobRequestVO); + + PageResult> updateJob(JobRequestVO jobRequestVO); + +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/convert/JobResponseVOConverter.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/convert/JobResponseVOConverter.java new file mode 100644 index 000000000..8a194df57 --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/convert/JobResponseVOConverter.java @@ -0,0 +1,21 @@ +package com.aizuda.easy.retry.server.web.service.convert; + +import com.aizuda.easy.retry.server.web.model.response.JobResponseVO; +import com.aizuda.easy.retry.template.datasource.persistence.po.Job; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:50:40 + * @since 2.4.0 + */ +@Mapper +public interface JobResponseVOConverter { + + JobResponseVOConverter INSTANCE = Mappers.getMapper(JobResponseVOConverter.class); + + List toJobResponseVOs(List jobs); +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/JobServiceImpl.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/JobServiceImpl.java new file mode 100644 index 000000000..c850c3eb8 --- /dev/null +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/JobServiceImpl.java @@ -0,0 +1,57 @@ +package com.aizuda.easy.retry.server.web.service.impl; + +import com.aizuda.easy.retry.server.web.model.base.PageResult; +import com.aizuda.easy.retry.server.web.model.request.JobQueryVO; +import com.aizuda.easy.retry.server.web.model.request.JobRequestVO; +import com.aizuda.easy.retry.server.web.model.response.JobResponseVO; +import com.aizuda.easy.retry.server.web.service.JobService; +import com.aizuda.easy.retry.server.web.service.convert.JobResponseVOConverter; +import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobMapper; +import com.aizuda.easy.retry.template.datasource.persistence.po.Job; +import com.aizuda.easy.retry.template.datasource.persistence.po.RetryTask; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author www.byteblogs.com + * @date 2023-10-11 22:20:42 + * @since 2.4.0 + */ +@Service +public class JobServiceImpl implements JobService { + + @Autowired + private JobMapper jobMapper; + + @Override + public PageResult> getJobPage(JobQueryVO queryVO) { + + PageDTO pageDTO = new PageDTO<>(queryVO.getPage(), queryVO.getSize()); + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + PageDTO selectPage = jobMapper.selectPage(pageDTO, queryWrapper); + + List jobResponseList = JobResponseVOConverter.INSTANCE.toJobResponseVOs(selectPage.getRecords()); + + return new PageResult<>(pageDTO, jobResponseList); + } + + @Override + public PageResult> getJobDetail(Long id) { + return null; + } + + @Override + public PageResult> saveJob(JobRequestVO jobRequestVO) { + return null; + } + + @Override + public PageResult> updateJob(JobRequestVO jobRequestVO) { + return null; + } +} diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/RetryTaskServiceImpl.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/RetryTaskServiceImpl.java index d09debf7e..f53c7a61f 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/RetryTaskServiceImpl.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/RetryTaskServiceImpl.java @@ -97,9 +97,6 @@ public class RetryTaskServiceImpl implements RetryTaskService { @Autowired private List taskGenerators; @Autowired - @Qualifier("bitSetIdempotentStrategyHandler") - protected IdempotentStrategy idempotentStrategy; - @Autowired private List taskActuators; @Override @@ -323,7 +320,6 @@ public class RetryTaskServiceImpl implements RetryTaskService { public boolean manualTriggerRetryTask(ManualTriggerTaskRequestVO requestVO) { List uniqueIds = requestVO.getUniqueIds(); - String groupName = requestVO.getGroupName(); List list = accessTemplate.getRetryTaskAccess().list(requestVO.getGroupName(), new LambdaQueryWrapper() @@ -346,7 +342,6 @@ public class RetryTaskServiceImpl implements RetryTaskService { @Override public boolean manualTriggerCallbackTask(ManualTriggerTaskRequestVO requestVO) { List uniqueIds = requestVO.getUniqueIds(); - String groupName = requestVO.getGroupName(); List list = accessTemplate.getRetryTaskAccess().list(requestVO.getGroupName(), new LambdaQueryWrapper() @@ -366,29 +361,4 @@ public class RetryTaskServiceImpl implements RetryTaskService { return true; } - private WaitStrategy getRetryTaskWaitWaitStrategy(String groupName, String sceneName) { - - SceneConfig sceneConfig = accessTemplate.getSceneConfigAccess().getSceneConfigByGroupNameAndSceneName(groupName, sceneName); - Integer backOff = sceneConfig.getBackOff(); - - return WaitStrategies.WaitStrategyEnum.getWaitStrategy(backOff); - } - - private WaitStrategy getCallbackWaitWaitStrategy() { - // 回调失败每15min重试一次 - return WaitStrategies.WaitStrategyEnum.getWaitStrategy(WaitStrategies.WaitStrategyEnum.FIXED.getBackOff()); - } - - private void retryCountIncrement(RetryTask retryTask) { - Integer retryCount = retryTask.getRetryCount(); - retryTask.setRetryCount(++retryCount); - } - - private void productExecUnitActor(RetryExecutor retryExecutor, ActorRef actorRef) { - String groupIdHash = retryExecutor.getRetryContext().getRetryTask().getGroupName(); - Long retryId = retryExecutor.getRetryContext().getRetryTask().getId(); - idempotentStrategy.set(groupIdHash, retryId.intValue()); - - actorRef.tell(retryExecutor, actorRef); - } } diff --git a/frontend/src/api/jobApi.js b/frontend/src/api/jobApi.js new file mode 100644 index 000000000..3b77d46db --- /dev/null +++ b/frontend/src/api/jobApi.js @@ -0,0 +1,15 @@ +import request from '@/utils/request' +const jobApi = { + + jobList: '/job/list' +} + +export default jobApi + +export function getJobList (parameter) { + return request({ + url: jobApi.jobList, + method: 'get', + params: parameter + }) +} diff --git a/frontend/src/components/GlobalHeader/RightContent.vue b/frontend/src/components/GlobalHeader/RightContent.vue index 6a2cf20dc..669b9340b 100644 --- a/frontend/src/components/GlobalHeader/RightContent.vue +++ b/frontend/src/components/GlobalHeader/RightContent.vue @@ -1,7 +1,9 @@ diff --git a/frontend/src/config/defaultSettings.js b/frontend/src/config/defaultSettings.js index 119f18e6c..56904d673 100644 --- a/frontend/src/config/defaultSettings.js +++ b/frontend/src/config/defaultSettings.js @@ -15,16 +15,16 @@ export default { navTheme: 'dark', // theme for nav menu primaryColor: '#1890ff', // '#F5222D', // primary color of ant design - layout: 'topmenu', // nav menu position: `sidemenu` or `topmenu` - contentWidth: 'Fixed', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu - fixedHeader: false, // sticky header - fixSiderbar: false, // sticky siderbar + layout: 'sidemenu', // nav menu position: `sidemenu` or `topmenu` + contentWidth: 'Fluid', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu + fixedHeader: true, // sticky header + fixSiderbar: true, // sticky siderbar colorWeak: false, menu: { locale: true }, title: 'Easy Retry', pwa: false, - iconfontUrl: '', + iconfontUrl: 'https://www.easyretry.com/', production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true' } diff --git a/frontend/src/config/router.config.js b/frontend/src/config/router.config.js index 897e19f9c..7bfb6cd1f 100644 --- a/frontend/src/config/router.config.js +++ b/frontend/src/config/router.config.js @@ -131,9 +131,25 @@ export const asyncRouterMap = [ meta: { title: '新增或更新用户', icon: 'profile', permission: ['userForm'] } }, { - path: 'https://www.easyretry.com', - name: 'HelpDocs', - meta: { title: '帮助文档', icon: 'question-circle', target: '_blank' } + path: '/job', + name: 'Job', + component: RouteView, + redirect: '/list', + meta: { title: '任务调度管理', icon: 'profile', permission: ['retryLog'] }, + children: [ + { + path: '/list', + name: 'JobList', + component: () => import('@/views/job/JobList'), + meta: { title: '调度任务', icon: 'profile', permission: ['retryLog'] } + }, + { + path: '/retry-log/info', + name: 'RetryLogInfo', + component: () => import('@/views/task/RetryLogInfo'), + meta: { title: '任务批次', icon: 'profile', permission: ['retryLog'] } + } + ] } ] }, diff --git a/frontend/src/views/job/JobList.vue b/frontend/src/views/job/JobList.vue new file mode 100644 index 000000000..444de2e72 --- /dev/null +++ b/frontend/src/views/job/JobList.vue @@ -0,0 +1,398 @@ + + +