feat: 2.6.0
1. 优化定时任务回调重试 2. 优化工作流前端显示问题
This commit is contained in:
parent
ee5dfa962c
commit
c8a238b91c
@ -11,6 +11,7 @@ import com.aizuda.easy.retry.client.model.request.DispatchJobRequest;
|
||||
import com.aizuda.easy.retry.common.core.context.SpringContext;
|
||||
import com.aizuda.easy.retry.common.core.model.JobContext;
|
||||
import com.aizuda.easy.retry.common.core.model.Result;
|
||||
import com.aizuda.easy.retry.common.log.EasyRetryLog;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -36,19 +37,26 @@ public class JobEndPoint {
|
||||
JobContext jobContext = buildJobContext(dispatchJob);
|
||||
JobExecutorInfo jobExecutorInfo = JobExecutorInfoCache.get(jobContext.getExecutorInfo());
|
||||
if (Objects.isNull(jobExecutorInfo)) {
|
||||
EasyRetryLog.REMOTE.error("执行器配置有误. executorInfo:[{}]", dispatchJob.getExecutorInfo());
|
||||
return new Result<>("执行器配置有误", Boolean.FALSE);
|
||||
}
|
||||
|
||||
// 选择执行器
|
||||
Object executor = jobExecutorInfo.getExecutor();
|
||||
IJobExecutor jobExecutor;
|
||||
if (IJobExecutor.class.isAssignableFrom(executor.getClass())) {
|
||||
jobExecutor = (AbstractJobExecutor) executor;
|
||||
} else {
|
||||
jobExecutor = SpringContext.getBeanByType(AnnotationJobExecutor.class);
|
||||
try {
|
||||
// 选择执行器
|
||||
Object executor = jobExecutorInfo.getExecutor();
|
||||
IJobExecutor jobExecutor;
|
||||
if (IJobExecutor.class.isAssignableFrom(executor.getClass())) {
|
||||
jobExecutor = (AbstractJobExecutor) executor;
|
||||
} else {
|
||||
jobExecutor = SpringContext.getBeanByType(AnnotationJobExecutor.class);
|
||||
}
|
||||
|
||||
jobExecutor.jobExecute(jobContext);
|
||||
} catch (Exception e) {
|
||||
EasyRetryLog.REMOTE.error("客户端发生非预期异常. taskBatchId:[{}]", dispatchJob.getTaskBatchId());
|
||||
throw e;
|
||||
}
|
||||
|
||||
jobExecutor.jobExecute(jobContext);
|
||||
|
||||
return new Result<>(Boolean.TRUE);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class JobExecutorFutureCallback implements FutureCallback<ExecuteResult>
|
||||
|
||||
private static final JobNettyClient CLIENT = RequestBuilder.<JobNettyClient, NettyResult>newBuilder()
|
||||
.client(JobNettyClient.class)
|
||||
.callback(nettyResult -> LogUtils.info(log, "Data report successfully requestId:[{}]", nettyResult.getRequestId())).build();
|
||||
.callback(nettyResult -> EasyRetryLog.LOCAL.info("Job execute result report successfully requestId:[{}]", nettyResult.getRequestId())).build();
|
||||
|
||||
private final JobContext jobContext;
|
||||
|
||||
@ -41,7 +41,7 @@ public class JobExecutorFutureCallback implements FutureCallback<ExecuteResult>
|
||||
@Override
|
||||
public void onSuccess(ExecuteResult result) {
|
||||
// 上报执行成功
|
||||
EasyRetryLog.LOCAL.warn("任务执行成功 taskBatchId:[{}] [{}]", jobContext.getTaskBatchId(), JsonUtil.toJsonString(result));
|
||||
EasyRetryLog.REMOTE.info("任务执行成功 taskBatchId:[{}] [{}]", jobContext.getTaskBatchId(), JsonUtil.toJsonString(result));
|
||||
|
||||
if (Objects.isNull(result)) {
|
||||
result = ExecuteResult.success();
|
||||
@ -57,7 +57,7 @@ public class JobExecutorFutureCallback implements FutureCallback<ExecuteResult>
|
||||
try {
|
||||
CLIENT.dispatchResult(buildDispatchJobResultRequest(result, taskStatus));
|
||||
} catch (Exception e) {
|
||||
EasyRetryLog.LOCAL.error("执行结果上报异常.[{}]", jobContext.getTaskId(), e);
|
||||
EasyRetryLog.REMOTE.error("执行结果上报异常.[{}]", jobContext.getTaskId(), e);
|
||||
} finally {
|
||||
stopThreadPool();
|
||||
ThreadLocalLogUtil.removeContext();
|
||||
@ -67,7 +67,7 @@ public class JobExecutorFutureCallback implements FutureCallback<ExecuteResult>
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
// 上报执行失败
|
||||
log.error("任务执行失败 任务执行成功 taskBatchId:[{}]", jobContext.getTaskBatchId(), t);
|
||||
EasyRetryLog.REMOTE.error("任务执行失败 taskBatchId:[{}]", jobContext.getTaskBatchId(), t);
|
||||
try {
|
||||
|
||||
ExecuteResult failure = ExecuteResult.failure();
|
||||
@ -81,7 +81,7 @@ public class JobExecutorFutureCallback implements FutureCallback<ExecuteResult>
|
||||
buildDispatchJobResultRequest(failure, JobTaskStatusEnum.FAIL.getStatus())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
EasyRetryLog.LOCAL.error("执行结果上报异常.[{}]", jobContext.getTaskId(), e);
|
||||
EasyRetryLog.REMOTE.error("执行结果上报异常.[{}]", jobContext.getTaskId(), e);
|
||||
} finally {
|
||||
stopThreadPool();
|
||||
ThreadLocalLogUtil.removeContext();
|
||||
|
@ -3,6 +3,8 @@ package com.aizuda.easy.retry.server.model.dto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 工作流回调节点参数模型
|
||||
*
|
||||
* @author: xiaowoniu
|
||||
* @date : 2024-01-02
|
||||
* @since : 2.6.0
|
||||
|
@ -1,13 +1,13 @@
|
||||
package com.aizuda.easy.retry.server.common.handler;
|
||||
|
||||
import com.aizuda.easy.retry.common.core.log.LogUtils;
|
||||
import com.aizuda.easy.retry.common.log.EasyRetryLog;
|
||||
import com.aizuda.easy.retry.server.common.ClientLoadBalance;
|
||||
import com.aizuda.easy.retry.server.common.allocate.client.ClientLoadBalanceManager;
|
||||
import com.aizuda.easy.retry.server.common.allocate.client.ClientLoadBalanceManager.AllocationAlgorithmEnum;
|
||||
import com.aizuda.easy.retry.server.common.dto.RegisterNodeInfo;
|
||||
import com.aizuda.easy.retry.server.common.cache.CacheRegisterTable;
|
||||
import com.aizuda.easy.retry.server.common.dto.RegisterNodeInfo;
|
||||
import com.aizuda.easy.retry.template.datasource.access.AccessTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@ -22,11 +22,9 @@ import java.util.stream.Stream;
|
||||
* @date : 2023-01-10 14:18
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNodeAllocateHandler {
|
||||
|
||||
@Autowired
|
||||
protected AccessTemplate accessTemplate;
|
||||
private final AccessTemplate accessTemplate;
|
||||
|
||||
/**
|
||||
* 获取分配的节点
|
||||
@ -39,7 +37,7 @@ public class ClientNodeAllocateHandler {
|
||||
|
||||
Set<RegisterNodeInfo> serverNodes = CacheRegisterTable.getServerNodeSet(groupName, namespaceId);
|
||||
if (CollectionUtils.isEmpty(serverNodes)) {
|
||||
LogUtils.warn(log, "client node is null. groupName:[{}]", groupName);
|
||||
EasyRetryLog.LOCAL.warn("client node is null. groupName:[{}]", groupName);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public interface JobTaskConverter {
|
||||
|
||||
JobLogMessage toJobLogMessage(LogTaskDTO logTaskDTO);
|
||||
|
||||
JobLogDTO toJobLogDTO(JobExecutorContext context);
|
||||
LogMetaDTO toJobLogDTO(ClientCallbackContext context);
|
||||
|
||||
LogMetaDTO toJobLogDTO(JobExecutorResultDTO resultDTO);
|
||||
|
||||
|
@ -1,9 +1,28 @@
|
||||
package com.aizuda.easy.retry.server.job.task.support.callback;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
|
||||
import com.aizuda.easy.retry.common.log.EasyRetryLog;
|
||||
import com.aizuda.easy.retry.server.common.akka.ActorGenerator;
|
||||
import com.aizuda.easy.retry.server.common.dto.RegisterNodeInfo;
|
||||
import com.aizuda.easy.retry.server.common.util.ClientInfoUtils;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.LogMetaDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.RealJobExecutorDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.support.ClientCallbackHandler;
|
||||
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
||||
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.Job;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author www.byteblogs.com
|
||||
* @date 2023-10-03 23:12:33
|
||||
@ -11,12 +30,107 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
*/
|
||||
public abstract class AbstractClientCallbackHandler implements ClientCallbackHandler, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private JobTaskMapper jobTaskMapper;
|
||||
@Autowired
|
||||
private JobMapper jobMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void callback(ClientCallbackContext context) {
|
||||
|
||||
// 判定是否需要重试
|
||||
boolean needRetry = isNeedRetry(context);
|
||||
if (needRetry) {
|
||||
// 更新重试次数
|
||||
if (updateRetryCount(context)) {
|
||||
Job job = context.getJob();
|
||||
JobTask jobTask = context.getJobTask();
|
||||
RealJobExecutorDTO realJobExecutor = JobTaskConverter.INSTANCE.toRealJobExecutorDTO(JobTaskConverter.INSTANCE.toJobExecutorContext(job), jobTask);
|
||||
realJobExecutor.setClientId(ClientInfoUtils.clientId(context.getClientInfo()));
|
||||
ActorRef actorRef = ActorGenerator.jobRealTaskExecutorActor();
|
||||
actorRef.tell(realJobExecutor, actorRef);
|
||||
LogMetaDTO logMetaDTO = JobTaskConverter.INSTANCE.toJobLogDTO(context);
|
||||
EasyRetryLog.REMOTE.info("任务执行/调度失败执行重试. 重试次数:[{}] <|>{}<|>",
|
||||
jobTask.getRetryCount() + 1, logMetaDTO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 不需要重试执行回调
|
||||
doCallback(context);
|
||||
}
|
||||
|
||||
private boolean updateRetryCount(ClientCallbackContext context) {
|
||||
JobTask updateJobTask = new JobTask();
|
||||
updateJobTask.setRetryCount(1);
|
||||
String newClient = chooseNewClient(context);
|
||||
if (StrUtil.isNotBlank(newClient)) {
|
||||
updateJobTask.setClientInfo(newClient);
|
||||
// 覆盖老的的客户端信息
|
||||
context.setClientInfo(newClient);
|
||||
}
|
||||
|
||||
Job job = context.getJob();
|
||||
return SqlHelper.retBool(jobTaskMapper.update(updateJobTask, Wrappers.<JobTask>lambdaUpdate()
|
||||
.lt(JobTask::getRetryCount, job.getMaxRetryTimes())
|
||||
.eq(JobTask::getId, context.getTaskId())
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
private boolean isNeedRetry(ClientCallbackContext context) {
|
||||
|
||||
if (context.getTaskStatus().equals(JobTaskStatusEnum.FAIL.getStatus())) {
|
||||
|
||||
JobTask jobTask = jobTaskMapper.selectById(context.getTaskId());
|
||||
Job job = jobMapper.selectById(context.getJobId());
|
||||
if (Objects.isNull(jobTask) || Objects.isNull(job)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
if (jobTask.getRetryCount() < job.getMaxRetryTimes()) {
|
||||
context.setClientInfo(jobTask.getClientInfo());
|
||||
context.setJob(job);
|
||||
context.setJobTask(jobTask);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
protected String chooseNewClient(ClientCallbackContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void failRetry(ClientCallbackContext context) {
|
||||
|
||||
if (context.getTaskStatus().equals(JobTaskStatusEnum.FAIL.getStatus())) {
|
||||
JobTask jobTask = jobTaskMapper.selectById(context.getTaskId());
|
||||
Job job = jobMapper.selectById(context.getJobId());
|
||||
if (jobTask == null || job == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jobTask.getRetryCount() < job.getMaxRetryTimes()) {
|
||||
// 更新重试次数
|
||||
JobTask updateJobTask = new JobTask();
|
||||
updateJobTask.setRetryCount(1);
|
||||
boolean success = SqlHelper.retBool(jobTaskMapper.update(updateJobTask, Wrappers.<JobTask>lambdaUpdate()
|
||||
.lt(JobTask::getRetryCount, job.getMaxRetryTimes())
|
||||
.eq(JobTask::getId, context.getTaskId())
|
||||
));
|
||||
|
||||
if (success) {
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doCallback(ClientCallbackContext context);
|
||||
|
||||
@Override
|
||||
|
@ -2,8 +2,10 @@ package com.aizuda.easy.retry.server.job.task.support.callback;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
|
||||
import com.aizuda.easy.retry.common.log.EasyRetryLog;
|
||||
import com.aizuda.easy.retry.server.common.akka.ActorGenerator;
|
||||
import com.aizuda.easy.retry.server.common.util.ClientInfoUtils;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.LogMetaDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.RealJobExecutorDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.JobExecutorResultDTO;
|
||||
@ -39,30 +41,7 @@ public class BroadcastClientCallbackHandler extends AbstractClientCallbackHandle
|
||||
|
||||
@Override
|
||||
protected void doCallback(final ClientCallbackContext context) {
|
||||
if (context.getTaskStatus().equals(JobTaskStatusEnum.FAIL.getStatus())) {
|
||||
JobTask jobTask = jobTaskMapper.selectById(context.getTaskId());
|
||||
Job job = jobMapper.selectById(context.getJobId());
|
||||
if (jobTask == null || job == null) {
|
||||
return;
|
||||
}
|
||||
if (jobTask.getRetryCount() < job.getMaxRetryTimes()) {
|
||||
// 更新重试次数
|
||||
JobTask updateJobTask = new JobTask();
|
||||
updateJobTask.setRetryCount(1);
|
||||
boolean success = SqlHelper.retBool(jobTaskMapper.update(updateJobTask, Wrappers.<JobTask>lambdaUpdate()
|
||||
.lt(JobTask::getRetryCount, job.getMaxRetryTimes())
|
||||
.eq(JobTask::getId, context.getTaskId())
|
||||
));
|
||||
if (success) {
|
||||
RealJobExecutorDTO realJobExecutor = JobTaskConverter.INSTANCE.toRealJobExecutorDTO(JobTaskConverter.INSTANCE.toJobExecutorContext(job), jobTask);
|
||||
realJobExecutor.setClientId(ClientInfoUtils.clientId(jobTask.getClientInfo()));
|
||||
ActorRef actorRef = ActorGenerator.jobRealTaskExecutorActor();
|
||||
actorRef.tell(realJobExecutor, actorRef);
|
||||
// TODO 记录日志
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JobExecutorResultDTO jobExecutorResultDTO = JobTaskConverter.INSTANCE.toJobExecutorResultDTO(context);
|
||||
jobExecutorResultDTO.setTaskId(context.getTaskId());
|
||||
jobExecutorResultDTO.setMessage(context.getExecuteResult().getMessage());
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.aizuda.easy.retry.server.job.task.support.callback;
|
||||
|
||||
import com.aizuda.easy.retry.client.model.ExecuteResult;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.Job;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -35,5 +37,11 @@ public class ClientCallbackContext {
|
||||
|
||||
private ExecuteResult executeResult;
|
||||
|
||||
private String clientInfo;
|
||||
|
||||
private Job job;
|
||||
|
||||
private JobTask jobTask;
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,11 +3,14 @@ package com.aizuda.easy.retry.server.job.task.support.callback;
|
||||
import akka.actor.ActorRef;
|
||||
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
|
||||
import com.aizuda.easy.retry.common.core.enums.JobTaskTypeEnum;
|
||||
import com.aizuda.easy.retry.common.log.EasyRetryLog;
|
||||
import com.aizuda.easy.retry.server.common.akka.ActorGenerator;
|
||||
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.handler.ClientNodeAllocateHandler;
|
||||
import com.aizuda.easy.retry.server.common.util.ClientInfoUtils;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.JobExecutorResultDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.LogMetaDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.RealJobExecutorDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobMapper;
|
||||
@ -21,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author www.byteblogs.com
|
||||
@ -43,43 +47,23 @@ public class ClusterClientCallbackHandler extends AbstractClientCallbackHandler
|
||||
return JobTaskTypeEnum.CLUSTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String chooseNewClient(ClientCallbackContext context) {
|
||||
|
||||
// 选择重试的节点
|
||||
RegisterNodeInfo serverNode = clientNodeAllocateHandler.getServerNode(context.getJobId().toString(),
|
||||
context.getGroupName(), context.getNamespaceId(), context.getJob().getRouteKey());
|
||||
if (Objects.isNull(serverNode)) {
|
||||
log.error("无可执行的客户端信息. jobId:[{}]", context.getJobId());
|
||||
return null;
|
||||
}
|
||||
|
||||
return ClientInfoUtils.generate(serverNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCallback(ClientCallbackContext context) {
|
||||
|
||||
if (context.getTaskStatus().equals(JobTaskStatusEnum.FAIL.getStatus())) {
|
||||
JobTask jobTask = jobTaskMapper.selectById(context.getTaskId());
|
||||
Job job = jobMapper.selectById(context.getJobId());
|
||||
if (jobTask == null || job == null) {
|
||||
return;
|
||||
}
|
||||
if (jobTask.getRetryCount() < job.getMaxRetryTimes()) {
|
||||
// 选择重试的节点
|
||||
RegisterNodeInfo serverNode = clientNodeAllocateHandler.getServerNode(context.getJobId().toString(),
|
||||
context.getGroupName(), context.getNamespaceId(), job.getRouteKey());
|
||||
if (Objects.isNull(serverNode)) {
|
||||
log.error("无可执行的客户端信息. jobId:[{}]", context.getJobId());
|
||||
return;
|
||||
}
|
||||
String newClient = ClientInfoUtils.generate(serverNode);
|
||||
// 更新重试次数
|
||||
JobTask updateJobTask = new JobTask();
|
||||
updateJobTask.setClientInfo(newClient);
|
||||
updateJobTask.setRetryCount(1);
|
||||
boolean success = SqlHelper.retBool(jobTaskMapper.update(updateJobTask, Wrappers.<JobTask>lambdaUpdate()
|
||||
.lt(JobTask::getRetryCount, job.getMaxRetryTimes())
|
||||
.eq(JobTask::getId, context.getTaskId())
|
||||
));
|
||||
// 更新成功执行重试
|
||||
if (success) {
|
||||
RealJobExecutorDTO realJobExecutor = JobTaskConverter.INSTANCE.toRealJobExecutorDTO(JobTaskConverter.INSTANCE.toJobExecutorContext(job), jobTask);
|
||||
realJobExecutor.setClientId(ClientInfoUtils.clientId(newClient));
|
||||
ActorRef actorRef = ActorGenerator.jobRealTaskExecutorActor();
|
||||
actorRef.tell(realJobExecutor, actorRef);
|
||||
// TODO 记录日志
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
JobExecutorResultDTO jobExecutorResultDTO = JobTaskConverter.INSTANCE.toJobExecutorResultDTO(context);
|
||||
jobExecutorResultDTO.setTaskId(context.getTaskId());
|
||||
jobExecutorResultDTO.setMessage(context.getExecuteResult().getMessage());
|
||||
|
@ -45,40 +45,6 @@ public class ShardingClientCallbackHandler extends AbstractClientCallbackHandler
|
||||
|
||||
@Override
|
||||
protected void doCallback(final ClientCallbackContext context) {
|
||||
if (context.getTaskStatus().equals(JobTaskStatusEnum.FAIL.getStatus())) {
|
||||
JobTask jobTask = jobTaskMapper.selectById(context.getTaskId());
|
||||
Job job = jobMapper.selectById(context.getJobId());
|
||||
if (jobTask == null || job == null) {
|
||||
return;
|
||||
}
|
||||
if (jobTask.getRetryCount() < job.getMaxRetryTimes()) {
|
||||
Set<RegisterNodeInfo> nodes = CacheRegisterTable.getServerNodeSet(context.getGroupName(), context.getNamespaceId());
|
||||
if (CollUtil.isEmpty(nodes)) {
|
||||
log.error("无可执行的客户端信息. jobId:[{}]", context.getJobId());
|
||||
return;
|
||||
}
|
||||
RegisterNodeInfo serverNode = RandomUtil.randomEle(nodes.toArray(new RegisterNodeInfo[0]));
|
||||
String newClient = ClientInfoUtils.generate(serverNode);
|
||||
// 更新重试次数
|
||||
JobTask updateJobTask = new JobTask();
|
||||
updateJobTask.setClientInfo(newClient);
|
||||
updateJobTask.setRetryCount(1);
|
||||
boolean success = SqlHelper.retBool(
|
||||
jobTaskMapper.update(updateJobTask, Wrappers.<JobTask>lambdaUpdate()
|
||||
.lt(JobTask::getRetryCount, job.getMaxRetryTimes())
|
||||
.eq(JobTask::getId, context.getTaskId())
|
||||
)
|
||||
);
|
||||
if (success) {
|
||||
RealJobExecutorDTO realJobExecutor = JobTaskConverter.INSTANCE.toRealJobExecutorDTO(JobTaskConverter.INSTANCE.toJobExecutorContext(job), jobTask);
|
||||
realJobExecutor.setClientId(ClientInfoUtils.clientId(newClient));
|
||||
ActorRef actorRef = ActorGenerator.jobRealTaskExecutorActor();
|
||||
actorRef.tell(realJobExecutor, actorRef);
|
||||
// TODO 记录日志
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JobExecutorResultDTO jobExecutorResultDTO = JobTaskConverter.INSTANCE.toJobExecutorResultDTO(context);
|
||||
jobExecutorResultDTO.setTaskId(context.getTaskId());
|
||||
@ -90,4 +56,15 @@ public class ShardingClientCallbackHandler extends AbstractClientCallbackHandler
|
||||
actorRef.tell(jobExecutorResultDTO, actorRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String chooseNewClient(ClientCallbackContext context) {
|
||||
Set<RegisterNodeInfo> nodes = CacheRegisterTable.getServerNodeSet(context.getGroupName(), context.getNamespaceId());
|
||||
if (CollUtil.isEmpty(nodes)) {
|
||||
log.error("无可执行的客户端信息. jobId:[{}]", context.getJobId());
|
||||
return null;
|
||||
}
|
||||
|
||||
RegisterNodeInfo serverNode = RandomUtil.randomEle(nodes.toArray(new RegisterNodeInfo[0]));
|
||||
return ClientInfoUtils.generate(serverNode);
|
||||
}
|
||||
}
|
||||
|
@ -88,10 +88,10 @@ public class JobExecutorResultActor extends AbstractActor {
|
||||
}
|
||||
});
|
||||
|
||||
LogMetaDTO logMetaDTO = JobTaskConverter.INSTANCE.toJobLogDTO(result);
|
||||
// 防止客户端日志还未上报完成,导致日志时序错误
|
||||
logMetaDTO.setTimestamp(DateUtils.toEpochMilli(LocalDateTime.now().plusHours(1)));
|
||||
EasyRetryLog.REMOTE.info("taskId:[{}] 任务执行成功. <|>{}<|>", logMetaDTO.getTaskId(), logMetaDTO);
|
||||
// LogMetaDTO logMetaDTO = JobTaskConverter.INSTANCE.toJobLogDTO(result);
|
||||
// // 防止客户端日志还未上报完成,导致日志时序错误
|
||||
// logMetaDTO.setTimestamp(DateUtils.toEpochMilli(LocalDateTime.now().plusHours(1)));
|
||||
// EasyRetryLog.REMOTE.info("taskId:[{}] 任务执行成功. <|>{}<|>", logMetaDTO.getTaskId(), logMetaDTO);
|
||||
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(log, " job executor result exception. [{}]", result, e);
|
||||
|
@ -14,6 +14,7 @@ import com.aizuda.easy.retry.server.common.akka.ActorGenerator;
|
||||
import com.aizuda.easy.retry.server.common.cache.CacheRegisterTable;
|
||||
import com.aizuda.easy.retry.server.common.client.RequestBuilder;
|
||||
import com.aizuda.easy.retry.server.common.dto.RegisterNodeInfo;
|
||||
import com.aizuda.easy.retry.server.common.util.DateUtils;
|
||||
import com.aizuda.easy.retry.server.job.task.client.JobRpcClient;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.JobExecutorResultDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.dto.JobLogDTO;
|
||||
@ -69,10 +70,12 @@ public class RequestClientActor extends AbstractActor {
|
||||
|
||||
try {
|
||||
// 构建请求客户端对象
|
||||
Long timestamp = DateUtils.toNowMilli();
|
||||
JobRpcClient rpcClient = buildRpcClient(registerNodeInfo, realJobExecutorDTO);
|
||||
Result<Boolean> dispatch = rpcClient.dispatch(dispatchJobRequest);
|
||||
if (dispatch.getStatus() == StatusEnum.YES.getStatus() && Objects.equals(dispatch.getData(), Boolean.TRUE)) {
|
||||
LogMetaDTO logMetaDTO = JobTaskConverter.INSTANCE.toJobLogDTO(realJobExecutorDTO);
|
||||
logMetaDTO.setTimestamp(timestamp);
|
||||
EasyRetryLog.REMOTE.info("taskId:[{}] 任务调度成功. <|>{}<|>", logMetaDTO.getTaskId(), logMetaDTO);
|
||||
} else {
|
||||
// 客户端返回失败,则认为任务执行失败
|
||||
|
@ -92,9 +92,7 @@ public class CallbackWorkflowExecutor extends AbstractWorkflowExecutor {
|
||||
result = exchange.getBody();
|
||||
log.info("回调结果. webHook:[{}],参数: [{}]", decisionConfig.getWebhook(), result);
|
||||
} catch (Exception e) {
|
||||
// log.error("回调异常. webHook:[{}],参数: [{}]", decisionConfig.getWebhook(), context.getTaskResult(), e);
|
||||
|
||||
EasyRetryLog.LOCAL.error("回调异常. webHook:[{}],参数: [{}]", decisionConfig.getWebhook(), context.getTaskResult(), e);
|
||||
EasyRetryLog.REMOTE.error("回调异常. webHook:[{}],参数: [{}]", decisionConfig.getWebhook(), context.getTaskResult(), e);
|
||||
taskBatchStatus = JobTaskBatchStatusEnum.FAIL.getStatus();
|
||||
operationReason = JobOperationReasonEnum.WORKFLOW_CALLBACK_NODE_EXECUTOR_ERROR.getReason();
|
||||
jobTaskStatus = JobTaskStatusEnum.FAIL.getStatus();
|
||||
|
@ -27,6 +27,11 @@ public class JobBatchResponseVO {
|
||||
*/
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 工作流节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 任务信息id
|
||||
*/
|
||||
|
@ -102,25 +102,26 @@ public class JobBatchServiceImpl implements JobBatchService {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (jobTaskBatch.getTaskType().equals(TaskTypeEnum.JOB.getType())) {
|
||||
Job job = jobMapper.selectById(jobTaskBatch.getJobId());
|
||||
return JobBatchResponseVOConverter.INSTANCE.toJobBatchResponseVO(jobTaskBatch, job);
|
||||
}
|
||||
Job job = jobMapper.selectById(jobTaskBatch.getJobId());
|
||||
JobBatchResponseVO jobBatchResponseVO = JobBatchResponseVOConverter.INSTANCE.toJobBatchResponseVO(jobTaskBatch, job);
|
||||
|
||||
JobBatchResponseVO jobBatchResponseVO = JobBatchResponseVOConverter.INSTANCE.toJobBatchResponseVO(jobTaskBatch);
|
||||
|
||||
// 回调节点
|
||||
if (SystemConstants.CALLBACK_JOB_ID.equals(jobTaskBatch.getJobId())) {
|
||||
if (jobTaskBatch.getTaskType().equals(TaskTypeEnum.WORKFLOW.getType())) {
|
||||
WorkflowNode workflowNode = workflowNodeMapper.selectById(jobTaskBatch.getWorkflowNodeId());
|
||||
jobBatchResponseVO.setJobName(workflowNode.getNodeName());
|
||||
jobBatchResponseVO.setCallback(JsonUtil.parseObject(workflowNode.getNodeInfo(), CallbackConfig.class));
|
||||
}
|
||||
jobBatchResponseVO.setNodeName(workflowNode.getNodeName());
|
||||
|
||||
// 条件节点
|
||||
if (SystemConstants.DECISION_JOB_ID.equals(jobTaskBatch.getJobId())) {
|
||||
WorkflowNode workflowNode = workflowNodeMapper.selectById(jobTaskBatch.getWorkflowNodeId());
|
||||
jobBatchResponseVO.setJobName(workflowNode.getNodeName());
|
||||
jobBatchResponseVO.setDecision(JsonUtil.parseObject(workflowNode.getNodeInfo(), DecisionConfig.class));
|
||||
// 回调节点
|
||||
if (SystemConstants.CALLBACK_JOB_ID.equals(jobTaskBatch.getJobId())) {
|
||||
jobBatchResponseVO.setCallback(JsonUtil.parseObject(workflowNode.getNodeInfo(), CallbackConfig.class));
|
||||
jobBatchResponseVO.setExecutionAt(jobTaskBatch.getCreateDt());
|
||||
return jobBatchResponseVO;
|
||||
}
|
||||
|
||||
// 条件节点
|
||||
if (SystemConstants.DECISION_JOB_ID.equals(jobTaskBatch.getJobId())) {
|
||||
jobBatchResponseVO.setDecision(JsonUtil.parseObject(workflowNode.getNodeInfo(), DecisionConfig.class));
|
||||
jobBatchResponseVO.setExecutionAt(jobTaskBatch.getCreateDt());
|
||||
return jobBatchResponseVO;
|
||||
}
|
||||
}
|
||||
|
||||
return jobBatchResponseVO;
|
||||
|
@ -1,14 +1,18 @@
|
||||
package com.aizuda.easy.retry.server.web.service.impl;
|
||||
|
||||
import com.aizuda.easy.retry.common.core.enums.JobTaskBatchStatusEnum;
|
||||
import com.aizuda.easy.retry.common.core.util.JsonUtil;
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobLogQueryVO;
|
||||
import com.aizuda.easy.retry.server.web.model.response.JobLogResponseVO;
|
||||
import com.aizuda.easy.retry.server.web.service.JobLogService;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobLogMessageMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobTaskBatchMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobLogMessage;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTaskBatch;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@ -23,10 +27,10 @@ import java.util.stream.Collectors;
|
||||
* @since :2.4.0
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class JobLogServiceImpl implements JobLogService {
|
||||
|
||||
@Autowired
|
||||
private JobLogMessageMapper jobLogMessageMapper;
|
||||
private final JobLogMessageMapper jobLogMessageMapper;
|
||||
private final JobTaskBatchMapper jobTaskBatchMapper;
|
||||
|
||||
@Override
|
||||
public JobLogResponseVO getJobLogPage(final JobLogQueryVO queryVO) {
|
||||
@ -35,16 +39,25 @@ public class JobLogServiceImpl implements JobLogService {
|
||||
|
||||
LambdaQueryWrapper<JobLogMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper
|
||||
.select(JobLogMessage::getId, JobLogMessage::getLogNum)
|
||||
.ge(JobLogMessage::getId, queryVO.getStartId())
|
||||
.eq(JobLogMessage::getTaskId, queryVO.getTaskId());
|
||||
.select(JobLogMessage::getId, JobLogMessage::getLogNum)
|
||||
.ge(JobLogMessage::getId, queryVO.getStartId())
|
||||
.eq(JobLogMessage::getTaskId, queryVO.getTaskId());
|
||||
|
||||
queryWrapper.orderByAsc(JobLogMessage::getRealTime).orderByDesc(JobLogMessage::getId);
|
||||
PageDTO<JobLogMessage> selectPage = jobLogMessageMapper.selectPage(pageDTO, queryWrapper);
|
||||
List<JobLogMessage> records = selectPage.getRecords();
|
||||
if (CollectionUtils.isEmpty(records)) {
|
||||
|
||||
Long count = jobTaskBatchMapper.selectCount(
|
||||
new LambdaQueryWrapper<JobTaskBatch>()
|
||||
.in(JobTaskBatch::getTaskBatchStatus, JobTaskBatchStatusEnum.COMPLETED)
|
||||
);
|
||||
|
||||
JobLogResponseVO jobLogResponseVO = new JobLogResponseVO();
|
||||
jobLogResponseVO.setFinished(Boolean.TRUE);
|
||||
if (count > 0) {
|
||||
jobLogResponseVO.setFinished(Boolean.TRUE);
|
||||
}
|
||||
|
||||
return jobLogResponseVO;
|
||||
}
|
||||
|
||||
@ -70,7 +83,7 @@ public class JobLogServiceImpl implements JobLogService {
|
||||
List<String> originalList = JsonUtil.parseObject(jobLogMessage.getMessage(), List.class);
|
||||
int size = originalList.size() - fromIndex;
|
||||
List<String> pageList = originalList.stream().skip(fromIndex).limit(queryVO.getSize())
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (messages.size() + size >= queryVO.getSize()) {
|
||||
messages.addAll(pageList);
|
||||
|
@ -31,6 +31,7 @@ import com.aizuda.easy.retry.server.web.model.request.SystemUserQueryVO;
|
||||
import com.aizuda.easy.retry.server.web.model.request.SystemUserRequestVO;
|
||||
import com.aizuda.easy.retry.server.web.model.response.SystemUserResponseVO;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -48,18 +49,14 @@ import java.util.stream.Collectors;
|
||||
* @since 2022-03-05
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SystemUserServiceImpl implements SystemUserService {
|
||||
public static final long EXPIRE_TIME = 3600 * 24 * 1000;
|
||||
|
||||
public static final long EXPIRE_TIME = 3600 * 7 * 1000;
|
||||
|
||||
@Autowired
|
||||
private SystemUserMapper systemUserMapper;
|
||||
@Autowired
|
||||
private SystemUserPermissionMapper systemUserPermissionMapper;
|
||||
@Autowired
|
||||
private NamespaceMapper namespaceMapper;
|
||||
@Autowired
|
||||
private SystemProperties systemProperties;
|
||||
private final SystemUserMapper systemUserMapper;
|
||||
private final SystemUserPermissionMapper systemUserPermissionMapper;
|
||||
private final NamespaceMapper namespaceMapper;
|
||||
private final SystemProperties systemProperties;
|
||||
|
||||
@Override
|
||||
public SystemUserResponseVO login(SystemUserRequestVO requestVO) {
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -5,8 +5,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Easy Retry</title>
|
||||
<script type="module" crossorigin src="./assets/MlqLg9-Y.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/vhU7tY2l.css">
|
||||
<script type="module" crossorigin src="./assets/YpO3912B.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/yQfA4Ykm.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
Loading…
Reference in New Issue
Block a user