feat:2.4.0
1. 任务调度日使用嵌套表格的形式,减少一次页面跳转 2. 修复重复任务问题 3. 修复新增JOb没有进行分桶
This commit is contained in:
parent
f8e04959b7
commit
b4836413f2
@ -53,6 +53,11 @@ public class JobTaskBatchGenerator {
|
||||
|
||||
Assert.isTrue(1 == jobTaskBatchMapper.insert(jobTaskBatch), () -> new EasyRetryServerException("新增调度任务失败.jobId:[{}]", context.getJobId()));
|
||||
|
||||
// 非待处理状态无需进入时间轮中
|
||||
if (JobTaskBatchStatusEnum.WAITING.getStatus() != jobTaskBatch.getTaskBatchStatus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 进入时间轮
|
||||
long delay = context.getNextTriggerAt().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
|
||||
- System.currentTimeMillis();
|
||||
|
@ -2,6 +2,7 @@ package com.aizuda.easy.retry.server.job.task.support.prepare;
|
||||
|
||||
import com.aizuda.easy.retry.common.core.enums.JobOperationReasonEnum;
|
||||
import com.aizuda.easy.retry.common.core.enums.JobTaskBatchStatusEnum;
|
||||
import com.aizuda.easy.retry.common.core.util.JsonUtil;
|
||||
import com.aizuda.easy.retry.server.job.task.support.BlockStrategy;
|
||||
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.JobTaskPrepareDTO;
|
||||
@ -38,7 +39,7 @@ public class RunningJobPrepareHandler extends AbstractJobPrePareHandler {
|
||||
|
||||
@Override
|
||||
protected void doHandler(JobTaskPrepareDTO prepare) {
|
||||
log.info("存在运行中的任务. taskBatchId:[{}]", prepare.getTaskBatchId());
|
||||
log.info("存在运行中的任务. prepare:[{}]", JsonUtil.toJsonString(prepare));
|
||||
|
||||
// 若存在所有的任务都是完成,但是批次上的状态为运行中,则是并发导致的未把批次状态变成为终态,此处做一次兜底处理
|
||||
int blockStrategy = prepare.getBlockStrategy();
|
||||
|
@ -25,6 +25,8 @@ public abstract class AbstractJobTaskStopHandler implements JobTaskStopHandler,
|
||||
@Autowired
|
||||
private JobTaskMapper jobTaskMapper;
|
||||
|
||||
protected abstract void doStop(TaskStopJobContext context);
|
||||
|
||||
@Override
|
||||
public void stop(TaskStopJobContext context) {
|
||||
|
||||
@ -59,8 +61,6 @@ public abstract class AbstractJobTaskStopHandler implements JobTaskStopHandler,
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doStop(TaskStopJobContext context);
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
JobTaskStopFactory.registerTaskStop(getTaskType(), this);
|
||||
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
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
@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0aa660"],{"119c":function(t,a,e){"use strict";e.r(a);e("b0c0");var o=function(){var t=this,a=t._self._c;return a("div",[a("page-header-wrapper",{staticStyle:{margin:"-24px -1px 0"},on:{back:function(){return t.$router.go(-1)}}},[a("div")]),null!==t.jobBatchInfo?a("a-card",{attrs:{bordered:!1}},[a("a-descriptions",{attrs:{title:"",column:3,bordered:""}},[a("a-descriptions-item",{attrs:{label:"组名称"}},[t._v(" "+t._s(t.jobBatchInfo.groupName)+" ")]),a("a-descriptions-item",{attrs:{label:"任务名称"}},[t._v(" "+t._s(t.jobBatchInfo.jobName)+" ")]),a("a-descriptions-item",{attrs:{label:"状态"}},[a("a-tag",{attrs:{color:t.taskBatchStatus[t.jobBatchInfo.taskBatchStatus].color}},[t._v(" "+t._s(t.taskBatchStatus[t.jobBatchInfo.taskBatchStatus].name)+" ")])],1),a("a-descriptions-item",{attrs:{label:"执行器类型"}},[a("a-tag",{attrs:{color:t.executorType[t.jobBatchInfo.executorType].color}},[t._v(" "+t._s(t.executorType[t.jobBatchInfo.executorType].name)+" ")])],1),a("a-descriptions-item",{attrs:{label:"操作原因"}},[a("a-tag",{attrs:{color:t.operationReason[t.jobBatchInfo.operationReason].color}},[t._v(" "+t._s(t.operationReason[t.jobBatchInfo.operationReason].name)+" ")])],1),a("a-descriptions-item",{attrs:{label:"开始执行时间"}},[t._v(" "+t._s(t.jobBatchInfo.executionAt)+" ")]),a("a-descriptions-item",{attrs:{label:"执行器名称",span:"4"}},[t._v(" "+t._s(t.jobBatchInfo.executorInfo)+" ")]),a("a-descriptions-item",{attrs:{label:"创建时间"}},[t._v(" "+t._s(t.jobBatchInfo.createDt)+" ")])],1)],1):t._e(),a("div",{staticStyle:{margin:"20px 0","border-left":"#f5222d 5px solid","font-size":"medium","font-weight":"bold"}},[t._v(" 任务项列表 ")]),a("JobTaskList",{ref:"JobTaskListRef"})],1)},r=[],s=e("3b7a"),n=e("c1df"),c=e.n(n),i=e("38b7"),u=e.n(i),p=e("36e8"),b={name:"JobInfo",components:{JobTaskList:p["default"]},data:function(){return{jobBatchInfo:null,taskBatchStatus:u.a.taskBatchStatus,operationReason:u.a.operationReason,taskType:u.a.taskType,triggerType:u.a.triggerType,blockStrategy:u.a.blockStrategy,executorType:u.a.executorType}},created:function(){var t=this,a=this.$route.query.id,e=this.$route.query.groupName;a&&e?Object(s["d"])(a).then((function(e){t.jobBatchInfo=e.data,t.queryParam={groupName:t.jobBatchInfo.groupName,taskBatchId:a},t.$refs.JobTaskListRef.refreshTable(t.queryParam)})):this.$router.push({path:"/404"})},methods:{jobTaskList:s["h"],parseDate:function(t){return c()(t).format("YYYY-MM-DD HH:mm:ss")}}},l=b,f=e("2877"),h=Object(f["a"])(l,o,r,!1,null,"1a941578",null);a["default"]=h.exports}}]);
|
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
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
@ -14,4 +14,5 @@ import lombok.EqualsAndHashCode;
|
||||
public class JobLogQueryVO extends BaseQueryVO {
|
||||
private Long jobId;
|
||||
private Long taskBatchId;
|
||||
private Long taskId;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ public class JobLogResponseVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long key;
|
||||
|
||||
/**
|
||||
* 组名称
|
||||
*/
|
||||
|
@ -14,6 +14,8 @@ public class JobTaskResponseVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long key;
|
||||
|
||||
/**
|
||||
* 组名称
|
||||
*/
|
||||
|
@ -3,6 +3,8 @@ package com.aizuda.easy.retry.server.web.service.convert;
|
||||
import com.aizuda.easy.retry.server.web.model.response.JobTaskResponseVO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
@ -17,5 +19,8 @@ public interface JobTaskResponseVOConverter {
|
||||
|
||||
JobTaskResponseVOConverter INSTANCE = Mappers.getMapper(JobTaskResponseVOConverter.class);
|
||||
|
||||
@Mappings(
|
||||
@Mapping(source = "id", target = "key")
|
||||
)
|
||||
List<JobTaskResponseVO> toJobTaskResponseVOs(List<JobTask> jobTasks);
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ public class JobLogServiceImpl implements JobLogService {
|
||||
queryWrapper.eq(JobLogMessage::getTaskBatchId, queryVO.getTaskBatchId());
|
||||
}
|
||||
|
||||
if (Objects.nonNull(queryVO.getTaskId())) {
|
||||
queryWrapper.eq(JobLogMessage::getTaskId, queryVO.getTaskId());
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc(JobLogMessage::getId);
|
||||
PageDTO<JobLogMessage> selectPage = jobLogMessageMapper.selectPage(pageDTO, queryWrapper);
|
||||
|
||||
|
@ -45,6 +45,10 @@ public class JobTaskServiceImpl implements JobTaskService {
|
||||
|
||||
List<JobTaskResponseVO> jobTaskResponseVOs = JobTaskResponseVOConverter.INSTANCE.toJobTaskResponseVOs(
|
||||
selectPage.getRecords());
|
||||
for (JobTaskResponseVO jobTaskResponseVO : jobTaskResponseVOs) {
|
||||
jobTaskResponseVO.setKey(jobTaskResponseVO.getId());
|
||||
}
|
||||
|
||||
return new PageResult<>(pageDTO, jobTaskResponseVOs);
|
||||
}
|
||||
}
|
||||
|
@ -67,23 +67,18 @@
|
||||
</div>
|
||||
<div class="table-operator">
|
||||
<a-dropdown v-action:edit v-if="selectedRowKeys.length > 0">
|
||||
<a-menu slot="overlay" @click="onClick">
|
||||
<a-menu-item key="1"><a-icon type="delete" />删除</a-menu-item>
|
||||
<a-menu-item key="2"><a-icon type="edit" />更新</a-menu-item>
|
||||
</a-menu>
|
||||
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /> </a-button>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
|
||||
<s-table
|
||||
ref="table"
|
||||
size="default"
|
||||
:rowKey="(record) => record.id"
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data="loadData"
|
||||
:alert="options.alert"
|
||||
:rowSelection="options.rowSelection"
|
||||
:scroll="{ x: 2000 }"
|
||||
:dataSource="data"
|
||||
:pagination="pagination"
|
||||
:loading="memberLoading"
|
||||
:scroll="{ x: 1200 }"
|
||||
rowKey="id"
|
||||
@expand="getRows"
|
||||
>
|
||||
<span slot="serial" slot-scope="text, record">
|
||||
{{ record.id }}
|
||||
@ -96,17 +91,20 @@
|
||||
<span slot="clientInfo" slot-scope="text">
|
||||
{{ text !== '' ? text.split('@')[1] : '' }}
|
||||
</span>
|
||||
<!-- <p slot="expandedRowRender" style="margin: 0" slot-scope="record">-->
|
||||
<!-- 执行结果: {{ record.resultMessage }}<br/>-->
|
||||
<!-- 参数: {{ record.argsStr }}-->
|
||||
<!-- </p>-->
|
||||
<span slot="action" slot-scope="text, record">
|
||||
<template>
|
||||
<a @click="handleLog(record)">日志</a>
|
||||
</template>
|
||||
</span>
|
||||
</s-table>
|
||||
|
||||
<a-table
|
||||
slot="expandedRowRender"
|
||||
slot-scope="record"
|
||||
:columns="logColumns"
|
||||
:data-source="loadData(record)"
|
||||
:pagination="false"
|
||||
rowKey="id"
|
||||
>
|
||||
<span slot="serial" slot-scope="text, record">
|
||||
{{ record.id }}
|
||||
</span>
|
||||
</a-table>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
@ -114,10 +112,11 @@
|
||||
import ATextarea from 'ant-design-vue/es/input/TextArea'
|
||||
import AInput from 'ant-design-vue/es/input/Input'
|
||||
import { STable } from '@/components'
|
||||
import { jobTaskList } from '@/api/jobApi'
|
||||
import { getAllGroupNameList } from '@/api/manage'
|
||||
import { jobLogList, jobTaskList } from '@/api/jobApi'
|
||||
import enums from '@/utils/jobEnum'
|
||||
import JobLogMessageList from './JobLogMessageList'
|
||||
import moment from 'moment/moment'
|
||||
|
||||
export default {
|
||||
name: 'JobTaskList',
|
||||
components: {
|
||||
@ -129,13 +128,13 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
currentComponet: 'List',
|
||||
record: '',
|
||||
mdl: {},
|
||||
visible: false,
|
||||
// 高级搜索 展开/关闭
|
||||
advanced: false,
|
||||
// 查询参数
|
||||
queryParam: {},
|
||||
data: [],
|
||||
logData: [],
|
||||
taskStatus: enums.taskStatus,
|
||||
// 表头
|
||||
columns: [
|
||||
@ -177,27 +176,29 @@ export default {
|
||||
dataIndex: 'createDt',
|
||||
sorter: true,
|
||||
width: '10%'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
fixed: 'right',
|
||||
dataIndex: 'action',
|
||||
width: '180px',
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
],
|
||||
// 加载数据方法 必须为 Promise 对象
|
||||
loadData: (parameter) => {
|
||||
if (this.queryParam.taskBatchId === null || this.queryParam.taskBatchId === undefined) {
|
||||
return []
|
||||
logColumns: [
|
||||
{
|
||||
title: '#',
|
||||
scopedSlots: { customRender: 'serial' },
|
||||
width: '5%'
|
||||
},
|
||||
{
|
||||
title: '信息',
|
||||
dataIndex: 'message',
|
||||
width: '50%'
|
||||
},
|
||||
{
|
||||
title: '执行时间',
|
||||
dataIndex: 'createDt',
|
||||
sorter: true,
|
||||
customRender: (text) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
|
||||
width: '10%'
|
||||
}
|
||||
return jobTaskList(Object.assign(parameter, this.queryParam)).then((res) => {
|
||||
return res
|
||||
})
|
||||
},
|
||||
],
|
||||
selectedRowKeys: [],
|
||||
selectedRows: [],
|
||||
|
||||
// custom table alert & rowSelection
|
||||
options: {
|
||||
alert: {
|
||||
@ -213,125 +214,66 @@ export default {
|
||||
},
|
||||
optionAlertShow: false,
|
||||
groupNameList: [],
|
||||
sceneList: []
|
||||
sceneList: [],
|
||||
memberLoading: false,
|
||||
pagination: {},
|
||||
logPagination: {}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
getAllGroupNameList().then((res) => {
|
||||
this.groupNameList = res.data
|
||||
if (this.groupNameList !== null && this.groupNameList.length > 0) {
|
||||
this.queryParam['groupName'] = this.groupNameList[0]
|
||||
this.$refs.table.refresh(true)
|
||||
this.handleChange(this.groupNameList[0])
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleNew () {
|
||||
this.$refs.saveRetryTask.isShow(true, null)
|
||||
},
|
||||
handleBatchNew () {
|
||||
this.$refs.batchSaveRetryTask.isShow(true, null)
|
||||
loadData (record) {
|
||||
const foundItem = this.logData.filter(item => item.taskId === record.id)
|
||||
console.log(record)
|
||||
console.log(foundItem)
|
||||
return foundItem
|
||||
},
|
||||
handleChange (value) {
|
||||
},
|
||||
toggleAdvanced () {
|
||||
this.advanced = !this.advanced
|
||||
},
|
||||
handleLog (record) {
|
||||
this.$router.push({ path: '/job/log/list', query: { taskBatchId: record.taskBatchId, jobId: record.jobId } })
|
||||
getRows (expanded, record) {
|
||||
console.log(record)
|
||||
if (expanded) {
|
||||
this.fetchLog({
|
||||
taskBatchId: record.taskBatchId,
|
||||
jobId: record.jobId,
|
||||
taskId: record.id
|
||||
}, record)
|
||||
}
|
||||
},
|
||||
handleOk (record) {},
|
||||
handleSuspend (record) {
|
||||
// updateRetryTaskStatus({ id: record.id, groupName: record.groupName, retryStatus: 3 }).then((res) => {
|
||||
// const { status } = res
|
||||
// if (status === 0) {
|
||||
// this.$message.error('暂停失败')
|
||||
// } else {
|
||||
// this.$refs.table.refresh(true)
|
||||
// this.$message.success('暂停成功')
|
||||
// }
|
||||
// })
|
||||
queryChange () {
|
||||
this.fetch()
|
||||
},
|
||||
handleRecovery (record) {
|
||||
// updateRetryTaskStatus({ id: record.id, groupName: record.groupName, retryStatus: 0 }).then((res) => {
|
||||
// const { status } = res
|
||||
// if (status === 0) {
|
||||
// this.$message.error('恢复失败')
|
||||
// } else {
|
||||
// this.$refs.table.refresh(true)
|
||||
// this.$message.success('恢复成功')
|
||||
// }
|
||||
// })
|
||||
},
|
||||
handleFinish (record) {
|
||||
// updateRetryTaskStatus({ id: record.id, groupName: record.groupName, retryStatus: 1 }).then((res) => {
|
||||
// const { status } = res
|
||||
// if (status === 0) {
|
||||
// this.$message.error('执行失败')
|
||||
// } else {
|
||||
// this.$refs.table.refresh(true)
|
||||
// this.$message.success('执行成功')
|
||||
// }
|
||||
// })
|
||||
},
|
||||
handleTrigger (record) {
|
||||
// if (record.taskType === 1) {
|
||||
// manualTriggerRetryTask({ groupName: record.groupName, uniqueIds: [ record.uniqueId ] }).then(res => {
|
||||
// const { status } = res
|
||||
// if (status === 0) {
|
||||
// this.$message.error('执行失败')
|
||||
// } else {
|
||||
// this.$refs.table.refresh(true)
|
||||
// this.$message.success('执行成功')
|
||||
// }
|
||||
// })
|
||||
// } else {
|
||||
// manualTriggerCallbackTask({ groupName: record.groupName, uniqueIds: [ record.uniqueId ] }).then(res => {
|
||||
// const { status } = res
|
||||
// if (status === 0) {
|
||||
// this.$message.error('执行失败')
|
||||
// } else {
|
||||
// this.$refs.table.refresh(true)
|
||||
// this.$message.success('执行完成')
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
fetch () {
|
||||
this.loading = true
|
||||
jobTaskList(this.queryParam).then(res => {
|
||||
this.data = res.data
|
||||
const pagination = { ...this.pagination }
|
||||
|
||||
pagination.pageSize = res.size
|
||||
pagination.current = res.page
|
||||
pagination.total = res.total
|
||||
|
||||
this.pagination = pagination
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
refreshTable (v) {
|
||||
this.queryParam = v
|
||||
this.$refs.table.refresh(true)
|
||||
this.queryChange()
|
||||
},
|
||||
async fetchLog (queryParam, record) {
|
||||
const res = await jobLogList(queryParam)
|
||||
console.log(this.logData)
|
||||
this.logData.push(...res.data)
|
||||
},
|
||||
onSelectChange (selectedRowKeys, selectedRows) {
|
||||
this.selectedRowKeys = selectedRowKeys
|
||||
this.selectedRows = selectedRows
|
||||
},
|
||||
handlerDel () {
|
||||
// var that = this
|
||||
// this.$confirm({
|
||||
// title: '您要删除这些数据吗?',
|
||||
// content: h => <div style="color:red;">删除后数据不可恢复,请确认!</div>,
|
||||
// onOk () {
|
||||
// batchDelete({ groupName: that.selectedRows[0].groupName, ids: that.selectedRowKeys }).then(res => {
|
||||
// that.$refs.table.refresh(true)
|
||||
// that.$message.success(`成功删除${res.data}条数据`)
|
||||
// that.selectedRowKeys = []
|
||||
// })
|
||||
// },
|
||||
// onCancel () {
|
||||
// },
|
||||
// class: 'test'
|
||||
// })
|
||||
},
|
||||
onClick ({ key }) {
|
||||
if (key === '2') {
|
||||
this.$refs.batchUpdateRetryTaskInfo.isShow(true, this.selectedRows, this.selectedRowKeys)
|
||||
return
|
||||
}
|
||||
|
||||
if (key === '1') {
|
||||
this.handlerDel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user