feat: 2.4.0

1. 优化页面支持常驻任务
2. 触发类型输入框支持文本和数字类型
3.修复分片的参数解析问题
This commit is contained in:
byteblogs168 2023-10-23 16:15:05 +08:00
parent 820cd7a3f4
commit 4d057510d3
46 changed files with 88 additions and 28 deletions

View File

@ -82,4 +82,8 @@ public interface SystemConstants {
interface DATE_FORMAT {
DateTimeFormatter YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
}
String JOB_SHARDING_VALUE_SEPARATOR = "#=@";
String JOB_SHARDING_ARGS_SEPARATOR = "#;@";
}

View File

@ -3,13 +3,12 @@ package com.aizuda.easy.retry.server.job.task.support.generator.task;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
import com.aizuda.easy.retry.common.core.enums.TaskTypeEnum;
import com.aizuda.easy.retry.server.common.cache.CacheRegisterTable;
import com.aizuda.easy.retry.server.common.dto.RegisterNodeInfo;
import com.aizuda.easy.retry.server.common.exception.EasyRetryServerException;
import com.aizuda.easy.retry.server.common.util.ClientInfoUtils;
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
import com.aizuda.easy.retry.common.core.enums.TaskTypeEnum;
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobMapper;
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobTaskMapper;
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
import com.google.common.collect.Lists;
@ -35,8 +34,6 @@ public class BroadcastTaskGenerator extends AbstractJobTaskGenerator {
@Autowired
private JobTaskMapper jobTaskMapper;
@Autowired
private JobMapper jobMapper;
@Override
public TaskTypeEnum getTaskInstanceType() {

View File

@ -2,6 +2,7 @@ package com.aizuda.easy.retry.server.job.task.support.generator.task;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
import com.aizuda.easy.retry.server.common.cache.CacheRegisterTable;
import com.aizuda.easy.retry.server.common.dto.RegisterNodeInfo;
@ -53,7 +54,7 @@ public class ShardingTaskGenerator extends AbstractJobTaskGenerator {
}
String argsStr = context.getArgsStr();
Map<String, String> split = Splitter.on(";").omitEmptyStrings().withKeyValueSeparator('=').split(argsStr);
Map<String, String> split = Splitter.on(SystemConstants.JOB_SHARDING_ARGS_SEPARATOR).omitEmptyStrings().withKeyValueSeparator(SystemConstants.JOB_SHARDING_VALUE_SEPARATOR).split(argsStr);
List<RegisterNodeInfo> nodeInfoList = new ArrayList<>(serverNodes);
List<JobTask> jobTasks = new ArrayList<>(split.size());

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.ant-cron-result{display:none}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7e5ff423"],{"3b7a":function(t,e,r){"use strict";r.d(e,"g",(function(){return u})),r.d(e,"j",(function(){return a})),r.d(e,"a",(function(){return s})),r.d(e,"l",(function(){return i})),r.d(e,"f",(function(){return b})),r.d(e,"h",(function(){return c})),r.d(e,"e",(function(){return d})),r.d(e,"d",(function(){return l})),r.d(e,"c",(function(){return f})),r.d(e,"b",(function(){return j})),r.d(e,"i",(function(){return h})),r.d(e,"k",(function(){return m}));var n=r("b775"),o={jobList:"/job/list",jobDetail:"/job/",saveJob:"/job/",updateJob:"/job/",updateJobStatus:"/job/status",delJob:"/job/",timeByCron:"/job/cron",jobNameList:"/job/job-name/list",jobBatchList:"/job/batch/list",jobBatchDetail:"/job/batch/",jobTaskList:"/job/task/list",jobLogList:"/job/log/list"};function u(t){return Object(n["b"])({url:o.jobNameList,method:"get",params:t})}function a(t){return Object(n["b"])({url:o.timeByCron,method:"get",params:t})}function s(t){return Object(n["b"])({url:o.delJob+t,method:"delete"})}function i(t){return Object(n["b"])({url:o.updateJobStatus,method:"put",data:t})}function b(t){return Object(n["b"])({url:o.jobLogList,method:"get",params:t})}function c(t){return Object(n["b"])({url:o.jobTaskList,method:"get",params:t})}function d(t){return Object(n["b"])({url:o.jobBatchList,method:"get",params:t})}function l(t){return Object(n["b"])({url:o.jobBatchDetail+t,method:"get"})}function f(t){return Object(n["b"])({url:o.jobList,method:"get",params:t})}function j(t){return Object(n["b"])({url:o.jobDetail+t,method:"get"})}function h(t){return Object(n["b"])({url:o.saveJob,method:"post",data:t})}function m(t){return Object(n["b"])({url:o.updateJob,method:"put",data:t})}},a03c:function(t,e,r){"use strict";r.r(e);var n=function(){var t=this,e=t._self._c;return e("div",[e("a-card",[e("s-table",{ref:"table",attrs:{size:"default",rowKey:"key",columns:t.columns,data:t.loadData},scopedSlots:t._u([{key:"serial",fn:function(r,n){return e("span",{},[t._v(" "+t._s(n.id)+" ")])}}])})],1)],1)},o=[],u=r("c1df"),a=r.n(u),s=r("2af9"),i=r("3b7a"),b={name:"JobLogList",components:{STable:s["j"]},data:function(){var t=this;return{columns:[{title:"#",scopedSlots:{customRender:"serial"},width:"5%"},{title:"信息",dataIndex:"message",width:"50%"},{title:"触发时间",dataIndex:"createDt",sorter:!0,customRender:function(t){return a()(t).format("YYYY-MM-DD HH:mm:ss")},width:"10%"}],queryParam:{},loadData:function(e){return Object(i["f"])(Object.assign(e,t.queryParam)).then((function(e){return t.total=e.total,e}))},total:0}},created:function(){var t=this.$route.query.taskBatchId,e=this.$route.query.jobId;t&&e?(this.queryParam={taskBatchId:t,jobId:e},this.$refs.table.refresh(!0)):this.$router.push({path:"/404"})},methods:{refreshTable:function(t){this.queryParam=t,this.$refs.table.refresh(!0)}}},c=b,d=r("2877"),l=Object(d["a"])(c,n,o,!1,null,"35165b21",null);e["default"]=l.exports}}]);

File diff suppressed because one or more lines are too long

View File

@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
@ -111,7 +112,7 @@ public class JobServiceImpl implements JobService {
if (Objects.nonNull(jobId)) {
queryWrapper.eq(Job::getId, jobId);
}
PageDTO<Job> pageDTO = new PageDTO<>(1, 20);
PageDTO<Job> selectPage = jobMapper.selectPage(pageDTO, queryWrapper);
return JobResponseVOConverter.INSTANCE.toJobResponseVOs(selectPage.getRecords());
@ -126,6 +127,25 @@ public class JobServiceImpl implements JobService {
waitStrategyContext.setTriggerInterval(jobRequestVO.getTriggerInterval());
waitStrategyContext.setNextTriggerAt(LocalDateTime.now());
job.setNextTriggerAt(waitStrategy.computeRetryTime(waitStrategyContext));
// 判断常驻任务
if (jobRequestVO.getTriggerType() == WaitStrategyEnum.FIXED.getTriggerType()) {
if (Integer.parseInt(jobRequestVO.getTriggerInterval()) < 10) {
job.setResident(StatusEnum.YES.getStatus());
}
} else if(jobRequestVO.getTriggerType() == WaitStrategyEnum.CRON.getTriggerType()) {
List<String> timeByCron = getTimeByCron(jobRequestVO.getTriggerInterval());
LocalDateTime first = LocalDateTime.parse(timeByCron.get(0), dateTimeFormatter);
LocalDateTime second = LocalDateTime.parse(timeByCron.get(1), dateTimeFormatter);
Duration duration = Duration.between(first, second);
long milliseconds = duration.toMillis();
if (milliseconds < 10 * 1000) {
job.setResident(StatusEnum.YES.getStatus());
}
} else {
throw new EasyRetryServerException("未知触发类型");
}
return 1 == jobMapper.insert(job);
}

View File

@ -87,6 +87,7 @@
<a-form-item label="触发类型">
<a-select
placeholder="请选择触发类型"
@change="handleChange"
v-decorator="[
'triggerType',
{
@ -100,7 +101,19 @@
</a-col>
<a-col :lg="16" :md="12" :sm="12">
<a-form-item label="间隔时长">
<a-input-number
v-if="triggerTypeValue === '2'"
style="width: -webkit-fill-available"
placeholder="请输入间隔时长(秒)"
:min="1"
v-decorator="[
'triggerInterval',
{initialValue: '60',
rules: [ { required: true, message: '请输入间隔时长'}]}
]" />
<a-input
v-if="triggerTypeValue === '1'"
@click="handlerCron"
placeholder="请输入间隔时长"
v-decorator="[
@ -341,7 +354,8 @@ export default {
routeKey: enums.routeKey,
loading: false,
visible: false,
count: 0
count: 0,
triggerTypeValue: '2'
}
},
beforeCreate () {
@ -365,6 +379,13 @@ export default {
})
},
methods: {
handleChange (value) {
console.log(value)
this.triggerTypeValue = value
this.form.setFieldsValue({
triggerInterval: null
})
},
handlerCron () {
const triggerType = this.form.getFieldValue('triggerType')
if (triggerType === '1') {
@ -413,11 +434,16 @@ export default {
const argsStr = this.form.getFieldValue('argsStr')
console.log(argsStr.includes('#=@'))
if (!argsStr.includes('#=@')) {
return
}
//
const keyValuePairs = argsStr.split(';')
const keyValuePairs = argsStr.split('#;@')
console.log(keyValuePairs)
const restoredArray = keyValuePairs.map(pair => {
const [index, value] = pair.split('=')
const [index, value] = pair.split('#=@')
console.log(value)
this.count++
return Number.parseInt(index)
@ -426,7 +452,7 @@ export default {
this.dynamicForm.getFieldDecorator('keys', { initialValue: restoredArray, preserve: true })
keyValuePairs.map(pair => {
const [index, value] = pair.split('=')
const [index, value] = pair.split('#=@')
this.dynamicForm.getFieldDecorator(`sharding[${index}]`, { initialValue: value, preserve: true })
return value
})
@ -445,7 +471,7 @@ export default {
if (!err) {
console.log(values)
const arr = values['sharding']
const formattedString = arr.map((item, index) => `${index}=${item}`).join(';')
const formattedString = arr.map((item, index) => `${index}#=@${item}`).join('#;@')
form.setFieldsValue({
argsStr: formattedString
})
@ -491,6 +517,7 @@ export default {
formData.executorType = formData.executorType.toString()
formData.blockStrategy = formData.blockStrategy.toString()
formData.triggerType = formData.triggerType.toString()
this.triggerTypeValue = formData.triggerType
form.setFieldsValue(formData)
})
}

View File

@ -120,7 +120,7 @@ const vueConfig = {
lintOnSave: undefined,
// babel-loader no-ignore node_modules/*
transpileDependencies: [],
outputDir: '../easy-retry-server/src/main/resources/admin',
outputDir: '../easy-retry-server/easy-retry-server-starter/src/main/resources/admin'
}
// preview.pro.loacg.com only do not use in your production;