feat(sj_1.0.0): 定时任务导出支持条件筛选

This commit is contained in:
opensnail 2024-05-30 22:52:45 +08:00
parent 553379b078
commit 7ee0253163
4 changed files with 77 additions and 29 deletions

View File

@ -5,6 +5,7 @@ import com.aizuda.snailjob.common.core.exception.SnailJobCommonException;
import com.aizuda.snailjob.server.web.annotation.LoginRequired; import com.aizuda.snailjob.server.web.annotation.LoginRequired;
import com.aizuda.snailjob.server.web.annotation.RoleEnum; import com.aizuda.snailjob.server.web.annotation.RoleEnum;
import com.aizuda.snailjob.server.web.model.base.PageResult; import com.aizuda.snailjob.server.web.model.base.PageResult;
import com.aizuda.snailjob.server.web.model.request.ExportJobVO;
import com.aizuda.snailjob.server.web.model.request.JobQueryVO; import com.aizuda.snailjob.server.web.model.request.JobQueryVO;
import com.aizuda.snailjob.server.web.model.request.JobRequestVO; import com.aizuda.snailjob.server.web.model.request.JobRequestVO;
import com.aizuda.snailjob.server.web.model.request.JobUpdateJobStatusRequestVO; import com.aizuda.snailjob.server.web.model.request.JobUpdateJobStatusRequestVO;
@ -109,8 +110,8 @@ public class JobController {
@PostMapping("/export") @PostMapping("/export")
@LoginRequired @LoginRequired
@OriginalControllerReturnValue @OriginalControllerReturnValue
public ResponseEntity<String> exportGroup(@RequestBody Set<Long> jobIds) { public ResponseEntity<String> exportGroup(@RequestBody ExportJobVO exportJobVO) {
return ExportUtils.doExport(jobService.exportJobs(jobIds)); return ExportUtils.doExport(jobService.exportJobs(exportJobVO));
} }
} }

View File

@ -0,0 +1,19 @@
package com.aizuda.snailjob.server.web.model.request;
import lombok.Data;
import java.util.Set;
/**
* @author opensnail
* @date 2024-05-30 21:49:19
* @since sj_1.0.0
*/
@Data
public class ExportJobVO {
private Set<Long> jobIds;
private String groupName;
private String jobName;
private Integer jobStatus;
}

View File

@ -1,6 +1,7 @@
package com.aizuda.snailjob.server.web.service; package com.aizuda.snailjob.server.web.service;
import com.aizuda.snailjob.server.web.model.base.PageResult; import com.aizuda.snailjob.server.web.model.base.PageResult;
import com.aizuda.snailjob.server.web.model.request.ExportJobVO;
import com.aizuda.snailjob.server.web.model.request.JobQueryVO; import com.aizuda.snailjob.server.web.model.request.JobQueryVO;
import com.aizuda.snailjob.server.web.model.request.JobRequestVO; import com.aizuda.snailjob.server.web.model.request.JobRequestVO;
import com.aizuda.snailjob.server.web.model.request.JobUpdateJobStatusRequestVO; import com.aizuda.snailjob.server.web.model.request.JobUpdateJobStatusRequestVO;
@ -10,7 +11,6 @@ import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author opensnail * @author opensnail
@ -28,8 +28,6 @@ public interface JobService {
Boolean updateJobStatus(JobUpdateJobStatusRequestVO jobRequestVO); Boolean updateJobStatus(JobUpdateJobStatusRequestVO jobRequestVO);
Job updateJobResident(JobRequestVO jobRequestVO);
Boolean deleteJobById(Long id); Boolean deleteJobById(Long id);
List<String> getTimeByCron(String cron); List<String> getTimeByCron(String cron);
@ -42,6 +40,6 @@ public interface JobService {
void importJobs(@Valid @NotEmpty(message = "导入数据不能为空") List<JobRequestVO> requestList); void importJobs(@Valid @NotEmpty(message = "导入数据不能为空") List<JobRequestVO> requestList);
String exportJobs(Set<Long> jobIds); String exportJobs(ExportJobVO exportJobVO);
} }

View File

@ -7,22 +7,22 @@ import cn.hutool.core.util.StrUtil;
import com.aizuda.snailjob.common.core.constant.SystemConstants; import com.aizuda.snailjob.common.core.constant.SystemConstants;
import com.aizuda.snailjob.common.core.enums.StatusEnum; import com.aizuda.snailjob.common.core.enums.StatusEnum;
import com.aizuda.snailjob.common.core.util.JsonUtil; import com.aizuda.snailjob.common.core.util.JsonUtil;
import com.aizuda.snailjob.common.core.util.StreamUtils;
import com.aizuda.snailjob.server.common.WaitStrategy; import com.aizuda.snailjob.server.common.WaitStrategy;
import com.aizuda.snailjob.server.common.config.SystemProperties; import com.aizuda.snailjob.server.common.config.SystemProperties;
import com.aizuda.snailjob.server.common.dto.PartitionTask;
import com.aizuda.snailjob.server.common.enums.JobTaskExecutorSceneEnum; import com.aizuda.snailjob.server.common.enums.JobTaskExecutorSceneEnum;
import com.aizuda.snailjob.server.common.exception.SnailJobServerException; import com.aizuda.snailjob.server.common.exception.SnailJobServerException;
import com.aizuda.snailjob.server.common.strategy.WaitStrategies; import com.aizuda.snailjob.server.common.strategy.WaitStrategies;
import com.aizuda.snailjob.server.common.util.CronUtils; import com.aizuda.snailjob.server.common.util.CronUtils;
import com.aizuda.snailjob.server.common.util.DateUtils; import com.aizuda.snailjob.server.common.util.DateUtils;
import com.aizuda.snailjob.server.common.util.PartitionTaskUtils;
import com.aizuda.snailjob.server.job.task.dto.JobTaskPrepareDTO; import com.aizuda.snailjob.server.job.task.dto.JobTaskPrepareDTO;
import com.aizuda.snailjob.server.job.task.support.JobPrepareHandler; import com.aizuda.snailjob.server.job.task.support.JobPrepareHandler;
import com.aizuda.snailjob.server.job.task.support.JobTaskConverter; import com.aizuda.snailjob.server.job.task.support.JobTaskConverter;
import com.aizuda.snailjob.server.job.task.support.cache.ResidentTaskCache; import com.aizuda.snailjob.server.job.task.support.cache.ResidentTaskCache;
import com.aizuda.snailjob.server.web.model.base.PageResult; import com.aizuda.snailjob.server.web.model.base.PageResult;
import com.aizuda.snailjob.server.web.model.request.JobQueryVO; import com.aizuda.snailjob.server.web.model.request.*;
import com.aizuda.snailjob.server.web.model.request.JobRequestVO;
import com.aizuda.snailjob.server.web.model.request.JobUpdateJobStatusRequestVO;
import com.aizuda.snailjob.server.web.model.request.UserSessionVO;
import com.aizuda.snailjob.server.web.model.response.JobResponseVO; import com.aizuda.snailjob.server.web.model.response.JobResponseVO;
import com.aizuda.snailjob.server.web.service.JobService; import com.aizuda.snailjob.server.web.service.JobService;
import com.aizuda.snailjob.server.web.service.convert.JobConverter; import com.aizuda.snailjob.server.web.service.convert.JobConverter;
@ -34,17 +34,20 @@ import com.aizuda.snailjob.template.datasource.persistence.po.GroupConfig;
import com.aizuda.snailjob.template.datasource.persistence.po.Job; import com.aizuda.snailjob.template.datasource.persistence.po.Job;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
/** /**
* @author opensnail * @author opensnail
@ -82,7 +85,6 @@ public class JobServiceImpl implements JobService {
UserSessionVO userSessionVO = UserSessionUtils.currentUserSession(); UserSessionVO userSessionVO = UserSessionUtils.currentUserSession();
PageDTO<Job> selectPage = jobMapper.selectPage(pageDTO, PageDTO<Job> selectPage = jobMapper.selectPage(pageDTO,
new LambdaQueryWrapper<Job>() new LambdaQueryWrapper<Job>()
.eq(Job::getDeleted, StatusEnum.NO.getStatus())
.eq(Job::getNamespaceId, userSessionVO.getNamespaceId()) .eq(Job::getNamespaceId, userSessionVO.getNamespaceId())
.in(userSessionVO.isUser(), Job::getGroupName, userSessionVO.getGroupNames()) .in(userSessionVO.isUser(), Job::getGroupName, userSessionVO.getGroupNames())
.eq(StrUtil.isNotBlank(queryVO.getGroupName()), Job::getGroupName, queryVO.getGroupName()) .eq(StrUtil.isNotBlank(queryVO.getGroupName()), Job::getGroupName, queryVO.getGroupName())
@ -128,11 +130,13 @@ public class JobServiceImpl implements JobService {
@Override @Override
public boolean saveJob(JobRequestVO jobRequestVO) { public boolean saveJob(JobRequestVO jobRequestVO) {
// 判断常驻任务 // 判断常驻任务
Job job = updateJobResident(jobRequestVO); Job job = JobConverter.INSTANCE.convert(jobRequestVO);
job.setResident(isResident(jobRequestVO));
job.setBucketIndex(HashUtil.bkdrHash(jobRequestVO.getGroupName() + jobRequestVO.getJobName()) job.setBucketIndex(HashUtil.bkdrHash(jobRequestVO.getGroupName() + jobRequestVO.getJobName())
% systemProperties.getBucketTotal()); % systemProperties.getBucketTotal());
job.setNextTriggerAt(calculateNextTriggerAt(jobRequestVO, DateUtils.toNowMilli())); job.setNextTriggerAt(calculateNextTriggerAt(jobRequestVO, DateUtils.toNowMilli()));
job.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId()); job.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId());
job.setId(null);
return 1 == jobMapper.insert(job); return 1 == jobMapper.insert(job);
} }
@ -144,7 +148,8 @@ public class JobServiceImpl implements JobService {
Assert.notNull(job, () -> new SnailJobServerException("更新失败")); Assert.notNull(job, () -> new SnailJobServerException("更新失败"));
// 判断常驻任务 // 判断常驻任务
Job updateJob = updateJobResident(jobRequestVO); Job updateJob = JobConverter.INSTANCE.convert(jobRequestVO);
updateJob.setResident(isResident(jobRequestVO));
updateJob.setNamespaceId(job.getNamespaceId()); updateJob.setNamespaceId(job.getNamespaceId());
// 工作流任务 // 工作流任务
@ -170,27 +175,24 @@ public class JobServiceImpl implements JobService {
return 1 == jobMapper.updateById(updateJob); return 1 == jobMapper.updateById(updateJob);
} }
@Override private Integer isResident(JobRequestVO jobRequestVO) {
public Job updateJobResident(JobRequestVO jobRequestVO) {
Job job = JobConverter.INSTANCE.convert(jobRequestVO);
job.setResident(StatusEnum.NO.getStatus());
if (Objects.equals(jobRequestVO.getTriggerType(), SystemConstants.WORKFLOW_TRIGGER_TYPE)) { if (Objects.equals(jobRequestVO.getTriggerType(), SystemConstants.WORKFLOW_TRIGGER_TYPE)) {
return job; return StatusEnum.NO.getStatus();
} }
if (jobRequestVO.getTriggerType() == WaitStrategies.WaitStrategyEnum.FIXED.getType()) { if (jobRequestVO.getTriggerType() == WaitStrategies.WaitStrategyEnum.FIXED.getType()) {
if (Integer.parseInt(jobRequestVO.getTriggerInterval()) < 10) { if (Integer.parseInt(jobRequestVO.getTriggerInterval()) < 10) {
job.setResident(StatusEnum.YES.getStatus()); return StatusEnum.YES.getStatus();
} }
} else if (jobRequestVO.getTriggerType() == WaitStrategies.WaitStrategyEnum.CRON.getType()) { } else if (jobRequestVO.getTriggerType() == WaitStrategies.WaitStrategyEnum.CRON.getType()) {
if (CronUtils.getExecuteInterval(jobRequestVO.getTriggerInterval()) < 10 * 1000) { if (CronUtils.getExecuteInterval(jobRequestVO.getTriggerInterval()) < 10 * 1000) {
job.setResident(StatusEnum.YES.getStatus()); return StatusEnum.YES.getStatus();
} }
} else { } else {
throw new SnailJobServerException("未知触发类型"); throw new SnailJobServerException("未知触发类型");
} }
return job; return StatusEnum.NO.getStatus();
} }
@Override @Override
@ -256,14 +258,42 @@ public class JobServiceImpl implements JobService {
} }
@Override @Override
public String exportJobs(Set<Long> jobIds) { public String exportJobs(ExportJobVO exportJobVO) {
if (CollUtil.isEmpty(jobIds)) { String namespaceId = UserSessionUtils.currentUserSession().getNamespaceId();
return StrUtil.EMPTY;
List<JobRequestVO> requestList = new ArrayList<>();
PartitionTaskUtils.process(startId -> {
List<Job> jobList = jobMapper.selectPage(new PageDTO<>(0, 100),
new LambdaQueryWrapper<Job>()
.eq(Job::getNamespaceId, namespaceId)
.eq(StrUtil.isNotBlank(exportJobVO.getGroupName()), Job::getGroupName, exportJobVO.getGroupName())
.likeRight(StrUtil.isNotBlank(exportJobVO.getJobName()), Job::getJobName, StrUtil.trim(exportJobVO.getJobName()))
.eq(Objects.nonNull(exportJobVO.getJobStatus()), Job::getJobStatus, exportJobVO.getJobStatus())
.in(CollUtil.isNotEmpty(exportJobVO.getJobIds()), Job::getId, exportJobVO.getJobIds())
.eq(Job::getDeleted, StatusEnum.NO.getStatus())
.gt(Job::getId, startId)
.orderByAsc(Job::getId)
).getRecords();
return StreamUtils.toList(jobList, JobPartitionTask::new);
},
partitionTasks -> {
List<JobPartitionTask> jobPartitionTasks = (List<JobPartitionTask>) partitionTasks;
requestList.addAll(JobConverter.INSTANCE.convertList(StreamUtils.toList(jobPartitionTasks, JobPartitionTask::getJob)));
}, 0);
return JsonUtil.toJsonString(requestList);
} }
List<Job> jobList = jobMapper.selectBatchIds(jobIds); @EqualsAndHashCode(callSuper = true)
jobList.forEach(job -> job.setId(null)); @Getter
return JsonUtil.toJsonString(JobConverter.INSTANCE.convertList(jobList)); private static class JobPartitionTask extends PartitionTask {
// 这里就直接放GroupConfig为了后面若加字段不需要再这里在调整了
private final Job job;
public JobPartitionTask(@NotNull Job job) {
this.job = job;
setId(job.getId());
}
} }
} }