feat(1.5.0-beta1): OpenApi支持重试任务的查询、触发、状态更新
This commit is contained in:
		
							parent
							
								
									03a5b73937
								
							
						
					
					
						commit
						5a5fd8e6ff
					
				| @ -1,4 +1,4 @@ | ||||
| package com.aizuda.snailjob.client.job.core.handler; | ||||
| package com.aizuda.snailjob.client.common.rpc.openapi; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| @ -12,6 +12,7 @@ public abstract class AbstractRequestHandler<R> implements RequestHandler<R> { | ||||
| 
 | ||||
|     /** | ||||
|      * 具体调用 | ||||
|      * | ||||
|      * @return | ||||
|      */ | ||||
|     @Override | ||||
| @ -27,9 +28,11 @@ public abstract class AbstractRequestHandler<R> implements RequestHandler<R> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected abstract void afterExecute(R r); | ||||
|     protected void afterExecute(R r) { | ||||
|     } | ||||
| 
 | ||||
|     protected abstract void beforeExecute(); | ||||
|     protected void beforeExecute() { | ||||
|     } | ||||
| 
 | ||||
|     protected abstract R doExecute(); | ||||
| 
 | ||||
| @ -0,0 +1,7 @@ | ||||
| package com.aizuda.snailjob.client.common.rpc.openapi; | ||||
| 
 | ||||
| public interface RequestHandler<R> { | ||||
| 
 | ||||
|     R execute(); | ||||
| 
 | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| package com.aizuda.snailjob.client.job.core.util; | ||||
| package com.aizuda.snailjob.client.common.util; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| @ -0,0 +1,18 @@ | ||||
| package com.aizuda.snailjob.client.job.core.handler; | ||||
| 
 | ||||
| import com.aizuda.snailjob.client.common.rpc.client.RequestBuilder; | ||||
| import com.aizuda.snailjob.client.common.rpc.openapi.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.openapi.JobOpenApiClient; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRpcResult; | ||||
| 
 | ||||
| /** | ||||
|  * @author opensnail | ||||
|  * @date 2024-09-29 20:40:10 | ||||
|  * @since sj_1.1.0 | ||||
|  */ | ||||
| public abstract class AbstractJobRequestHandler<R> extends AbstractRequestHandler<R> { | ||||
|     protected JobOpenApiClient client = RequestBuilder.<JobOpenApiClient, SnailJobRpcResult>newBuilder() | ||||
|             .client(JobOpenApiClient.class) | ||||
|             .async(false) | ||||
|             .build(); | ||||
| } | ||||
| @ -21,7 +21,7 @@ import static com.aizuda.snailjob.client.job.core.enums.TriggerTypeEnum.*; | ||||
|  * @date 2024-10-19 22:34:38 | ||||
|  * @since sj_1.2.0 | ||||
|  */ | ||||
| public abstract class AbstractParamsHandler<H, R> extends AbstractRequestHandler<R> { | ||||
| public abstract class AbstractParamsHandler<H, R> extends AbstractJobRequestHandler<R> { | ||||
|     protected static final String SHARD_NUM = "shardNum"; | ||||
|     @Getter | ||||
|     private final RequestAddOrUpdateJobDTO reqDTO; | ||||
|  | ||||
| @ -10,7 +10,7 @@ import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| 
 | ||||
| public abstract class AbstractTriggerHandler<H, R> extends AbstractRequestHandler<R> { | ||||
| public abstract class AbstractTriggerHandler<H, R> extends AbstractJobRequestHandler<R> { | ||||
|     @Getter | ||||
|     private final JobTriggerDTO reqDTO; | ||||
|     @Setter | ||||
|  | ||||
| @ -1,16 +0,0 @@ | ||||
| package com.aizuda.snailjob.client.job.core.handler; | ||||
| 
 | ||||
| import com.aizuda.snailjob.client.common.rpc.client.RequestBuilder; | ||||
| import com.aizuda.snailjob.client.job.core.openapi.OpenApiClient; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRpcResult; | ||||
| 
 | ||||
| public interface RequestHandler<R> { | ||||
| 
 | ||||
|     OpenApiClient client = RequestBuilder.<OpenApiClient, SnailJobRpcResult>newBuilder() | ||||
|             .client(OpenApiClient.class) | ||||
|             .async(false) | ||||
|             .build(); | ||||
| 
 | ||||
|     R execute(); | ||||
| 
 | ||||
| } | ||||
| @ -4,7 +4,7 @@ import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractParamsHandler; | ||||
| import com.aizuda.snailjob.client.job.core.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.client.common.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.common.core.enums.JobTaskTypeEnum; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
|  | ||||
| @ -3,7 +3,7 @@ package com.aizuda.snailjob.client.job.core.handler.delete; | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| @ -16,7 +16,7 @@ import java.util.Set; | ||||
|  * @Date:2024/11/21 22:38 | ||||
|  * @Filename:DeleteJobHandler | ||||
|  */ | ||||
| public class DeleteJobHandler extends AbstractRequestHandler<Boolean> { | ||||
| public class DeleteJobHandler extends AbstractJobRequestHandler<Boolean> { | ||||
|     private final Set<Long> toDeleteIds; | ||||
| 
 | ||||
|     public DeleteJobHandler(Set<Long> toDeleteIds) { | ||||
|  | ||||
| @ -3,7 +3,7 @@ package com.aizuda.snailjob.client.job.core.handler.delete; | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| @ -16,7 +16,7 @@ import java.util.Set; | ||||
|  * @Date:2024/11/21 22:42 | ||||
|  * @Filename:DeleteWorkflowHandler | ||||
|  */ | ||||
| public class DeleteWorkflowHandler extends AbstractRequestHandler<Boolean> { | ||||
| public class DeleteWorkflowHandler extends AbstractJobRequestHandler<Boolean> { | ||||
|     private final Set<Long> toDeleteIds; | ||||
| 
 | ||||
|     public DeleteWorkflowHandler(Set<Long> toDeleteIds) { | ||||
|  | ||||
| @ -5,14 +5,14 @@ import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.dto.JobResponseVO; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| public class RequestQueryHandler extends AbstractRequestHandler<JobResponseVO> { | ||||
| public class RequestQueryHandler extends AbstractJobRequestHandler<JobResponseVO> { | ||||
|     private final Long queryJobId; | ||||
| 
 | ||||
|     public RequestQueryHandler(Long queryJobId) { | ||||
|  | ||||
| @ -5,7 +5,7 @@ import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.dto.JobBatchResponseVO; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| @ -15,7 +15,7 @@ import java.util.Objects; | ||||
| /** | ||||
|  * @since 1.5.0 | ||||
|  */ | ||||
| public class RequestQueryJobBatchHandler extends AbstractRequestHandler<JobBatchResponseVO> { | ||||
| public class RequestQueryJobBatchHandler extends AbstractJobRequestHandler<JobBatchResponseVO> { | ||||
|     private final Long queryJobBatchId; | ||||
| 
 | ||||
|     public RequestQueryJobBatchHandler(Long queryJobBatchId) { | ||||
|  | ||||
| @ -5,7 +5,7 @@ import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.dto.WorkflowDetailResponseVO; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| @ -15,7 +15,7 @@ import java.util.Objects; | ||||
| /** | ||||
|  * @since 1.5.0 | ||||
|  */ | ||||
| public class RequestQueryWorkflowBatchHandler extends AbstractRequestHandler<WorkflowDetailResponseVO> { | ||||
| public class RequestQueryWorkflowBatchHandler extends AbstractJobRequestHandler<WorkflowDetailResponseVO> { | ||||
|     private final Long workflowBatchId; | ||||
| 
 | ||||
|     public RequestQueryWorkflowBatchHandler(Long workflowBatchId) { | ||||
|  | ||||
| @ -5,11 +5,10 @@ import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.enums.TriggerTypeEnum; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractParamsHandler; | ||||
| import com.aizuda.snailjob.client.job.core.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.client.common.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.common.core.enums.JobTaskTypeEnum; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| 
 | ||||
| 
 | ||||
| public abstract class UpdateHandler<H> extends AbstractParamsHandler<H, Boolean> { | ||||
|  | ||||
| @ -4,13 +4,13 @@ import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.dto.RequestUpdateStatusDTO; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.client.common.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| 
 | ||||
| public class UpdateJobStatusHandler extends AbstractRequestHandler<Boolean> { | ||||
| public class UpdateJobStatusHandler extends AbstractJobRequestHandler<Boolean> { | ||||
|     private final RequestUpdateStatusDTO statusDTO; | ||||
| 
 | ||||
|     public UpdateJobStatusHandler(Long id) { | ||||
|  | ||||
| @ -4,13 +4,13 @@ import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.job.core.dto.RequestUpdateStatusDTO; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.job.core.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.client.job.core.handler.AbstractJobRequestHandler; | ||||
| import com.aizuda.snailjob.client.common.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| 
 | ||||
| public class UpdateWorkflowStatusHandler extends AbstractRequestHandler<Boolean> { | ||||
| public class UpdateWorkflowStatusHandler extends AbstractJobRequestHandler<Boolean> { | ||||
|     private final RequestUpdateStatusDTO statusDTO; | ||||
| 
 | ||||
|     public UpdateWorkflowStatusHandler(Long id) { | ||||
|  | ||||
| @ -9,7 +9,7 @@ import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| import java.util.Set; | ||||
| 
 | ||||
| public interface OpenApiClient { | ||||
| public interface JobOpenApiClient { | ||||
|     @Mapping(method = RequestMethod.POST, path = "/api/job/add") | ||||
|     Result<Object> addJob(RequestAddOrUpdateJobDTO requestAddOrUpdateJobDTO); | ||||
| 
 | ||||
| @ -0,0 +1,10 @@ | ||||
| package com.aizuda.snailjob.client.core.dto; | ||||
| 
 | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.Data; | ||||
| 
 | ||||
| @Data | ||||
| public class RequestTriggerRetryDTO { | ||||
|     @NotNull(message = "id 不能为空") | ||||
|     private Long id; | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| package com.aizuda.snailjob.client.core.dto; | ||||
| 
 | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.Data; | ||||
| 
 | ||||
| @Data | ||||
| public class RequestUpdateRetryStatusDTO { | ||||
|     @NotNull(message = "id 不能为空") | ||||
|     private Long id; | ||||
| 
 | ||||
|     @NotNull(message = "retryStatus 不能为空") | ||||
|     private Integer retryStatus; | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| package com.aizuda.snailjob.client.core.dto; | ||||
| 
 | ||||
| import lombok.Data; | ||||
| 
 | ||||
| import java.time.LocalDateTime; | ||||
| 
 | ||||
| @Data | ||||
| public class RetryDTO { | ||||
|     private Long id; | ||||
| 
 | ||||
|     private String namespaceId; | ||||
| 
 | ||||
|     private String groupName; | ||||
| 
 | ||||
|     private String sceneName; | ||||
| 
 | ||||
|     private String idempotentId; | ||||
| 
 | ||||
|     private String bizNo; | ||||
| 
 | ||||
|     private String argsStr; | ||||
| 
 | ||||
|     private String extAttrs; | ||||
| 
 | ||||
|     private String executorName; | ||||
| 
 | ||||
|     /** | ||||
|      * 下次触发时间 | ||||
|      */ | ||||
|     private LocalDateTime nextTriggerAt; | ||||
| 
 | ||||
|     private Integer retryCount; | ||||
| 
 | ||||
|     private Integer retryStatus; | ||||
| 
 | ||||
|     private Integer taskType; | ||||
| 
 | ||||
|     private Long parentId; | ||||
| 
 | ||||
|     private Integer bucketIndex; | ||||
| 
 | ||||
|     private Long deleted; | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| package com.aizuda.snailjob.client.core.handler; | ||||
| 
 | ||||
| import com.aizuda.snailjob.client.common.rpc.client.RequestBuilder; | ||||
| import com.aizuda.snailjob.client.common.rpc.openapi.AbstractRequestHandler; | ||||
| import com.aizuda.snailjob.client.core.openapi.RetryOpenApiClient; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRpcResult; | ||||
| 
 | ||||
| public abstract class AbstractRetryRequestHandler<T> extends AbstractRequestHandler<T> { | ||||
|     RetryOpenApiClient client = RequestBuilder.<RetryOpenApiClient, SnailJobRpcResult>newBuilder() | ||||
|             .client(RetryOpenApiClient.class) | ||||
|             .async(false) | ||||
|             .build(); | ||||
| } | ||||
| @ -0,0 +1,35 @@ | ||||
| package com.aizuda.snailjob.client.core.handler; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.core.dto.RetryDTO; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| public class QueryRetryHandler extends AbstractRetryRequestHandler<RetryDTO> { | ||||
| 
 | ||||
|     private final Long retryId; | ||||
| 
 | ||||
|     public QueryRetryHandler(Long retryId) { | ||||
|         this.retryId = retryId; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected RetryDTO doExecute() { | ||||
|         Result<Object> result = client.queryRetryTask(retryId); | ||||
|         Assert.isTrue(StatusEnum.YES.getStatus() == result.getStatus(), | ||||
|                 () -> new SnailJobClientException(result.getMessage())); | ||||
|         Object data = result.getData(); | ||||
|         Assert.isTrue(Objects.nonNull(data), () -> new SnailJobClientException("获取[{}]任务详情失败", retryId)); | ||||
|         return JsonUtil.parseObject(JsonUtil.toJsonString(data), RetryDTO.class); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Pair<Boolean, String> checkRequest() { | ||||
|         return Pair.of(retryId != null && retryId > 0, "retryId不能为null并且必须大于0"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| package com.aizuda.snailjob.client.core.handler; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.common.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.client.core.dto.RequestTriggerRetryDTO; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| public class TriggerRetryHandler extends AbstractRetryRequestHandler<Boolean> { | ||||
| 
 | ||||
|     private final RequestTriggerRetryDTO triggerRetryDTO; | ||||
| 
 | ||||
|     public TriggerRetryHandler(Long retryId) { | ||||
|         this.triggerRetryDTO = new RequestTriggerRetryDTO(); | ||||
|         triggerRetryDTO.setId(retryId); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Boolean doExecute() { | ||||
|         Result<Object> result = client.triggerRetryTask(triggerRetryDTO); | ||||
|         Assert.isTrue(StatusEnum.YES.getStatus() == result.getStatus(), | ||||
|                 () -> new SnailJobClientException(result.getMessage())); | ||||
|         return (Boolean) result.getData(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Pair<Boolean, String> checkRequest() { | ||||
|         return ValidatorUtils.validateEntity(triggerRetryDTO); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| package com.aizuda.snailjob.client.core.handler; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.lang.Pair; | ||||
| import com.aizuda.snailjob.client.common.exception.SnailJobClientException; | ||||
| import com.aizuda.snailjob.client.common.util.ValidatorUtils; | ||||
| import com.aizuda.snailjob.client.core.dto.RequestUpdateRetryStatusDTO; | ||||
| import com.aizuda.snailjob.common.core.enums.RetryStatusEnum; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| public class UpdateRetryStatusHandler extends AbstractRetryRequestHandler<Boolean> { | ||||
| 
 | ||||
|     private final RequestUpdateRetryStatusDTO updateRetryStatusDTO; | ||||
| 
 | ||||
|     public UpdateRetryStatusHandler(Long retryId) { | ||||
|         this.updateRetryStatusDTO = new RequestUpdateRetryStatusDTO(); | ||||
|         updateRetryStatusDTO.setId(retryId); | ||||
|     } | ||||
| 
 | ||||
|     public UpdateRetryStatusHandler setRetryStatus(RetryStatusEnum retryStatusEnum) { | ||||
|         updateRetryStatusDTO.setRetryStatus(retryStatusEnum.getStatus()); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Boolean doExecute() { | ||||
|         Result<Object> result = client.updateRetryTaskStatus(updateRetryStatusDTO); | ||||
|         Assert.isTrue(StatusEnum.YES.getStatus() == result.getStatus(), | ||||
|                 () -> new SnailJobClientException(result.getMessage())); | ||||
|         return (Boolean) result.getData(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Pair<Boolean, String> checkRequest() { | ||||
|         return ValidatorUtils.validateEntity(updateRetryStatusDTO); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| package com.aizuda.snailjob.client.core.openapi; | ||||
| 
 | ||||
| import com.aizuda.snailjob.client.common.annotation.Mapping; | ||||
| import com.aizuda.snailjob.client.common.rpc.client.RequestMethod; | ||||
| import com.aizuda.snailjob.client.core.dto.RequestTriggerRetryDTO; | ||||
| import com.aizuda.snailjob.client.core.dto.RequestUpdateRetryStatusDTO; | ||||
| import com.aizuda.snailjob.common.core.model.Result; | ||||
| 
 | ||||
| public interface RetryOpenApiClient { | ||||
|     @Mapping(method = RequestMethod.POST, path = "/api/retry/query") | ||||
|     Result<Object> queryRetryTask(Long retryId); | ||||
| 
 | ||||
|     @Mapping(method = RequestMethod.POST, path = "/api/retry/triggerRetry") | ||||
|     Result<Object> triggerRetryTask(RequestTriggerRetryDTO triggerRetryDTO); | ||||
| 
 | ||||
|     @Mapping(method = RequestMethod.POST, path = "/api/retry/updateRetryStatus") | ||||
|     Result<Object> updateRetryTaskStatus(RequestUpdateRetryStatusDTO statusDTO); | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.aizuda.snailjob.client.core.openapi; | ||||
| 
 | ||||
| import com.aizuda.snailjob.client.core.handler.QueryRetryHandler; | ||||
| import com.aizuda.snailjob.client.core.handler.TriggerRetryHandler; | ||||
| import com.aizuda.snailjob.client.core.handler.UpdateRetryStatusHandler; | ||||
| 
 | ||||
| public class SnailRetryOpenApi { | ||||
| 
 | ||||
|     public static QueryRetryHandler queryTask(Long retryId) { | ||||
|         return new QueryRetryHandler(retryId); | ||||
|     } | ||||
| 
 | ||||
|     public static UpdateRetryStatusHandler updateTaskStatus(Long retryId) { | ||||
|         return new UpdateRetryStatusHandler(retryId); | ||||
|     } | ||||
| 
 | ||||
|     public static TriggerRetryHandler triggerTask(Long retryId) { | ||||
|         return new TriggerRetryHandler(retryId); | ||||
|     } | ||||
| } | ||||
| @ -167,6 +167,12 @@ public interface SystemConstants { | ||||
| 
 | ||||
|         String OPENAPI_DELETE_WORKFLOW = "/api/job/deleteWorkFlow"; | ||||
| 
 | ||||
|         String OPENAPI_ADD_RETRY = "/api/retry/query"; | ||||
| 
 | ||||
|         String OPENAPI_UPDATE_RETRY_STATUS = "/api/retry/updateRetryStatus"; | ||||
| 
 | ||||
|         String OPENAPI_TRIGGER_RETRY = "/api/retry/triggerRetry"; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     String LOGO = """ | ||||
|  | ||||
| @ -0,0 +1,29 @@ | ||||
| package com.aizuda.snailjob.server.common.convert; | ||||
| 
 | ||||
| import com.aizuda.snailjob.server.common.util.DateUtils; | ||||
| import com.aizuda.snailjob.server.common.vo.RetryResponseVO; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.Retry; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.Mapping; | ||||
| import org.mapstruct.Mappings; | ||||
| import org.mapstruct.factory.Mappers; | ||||
| 
 | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| @Mapper | ||||
| public interface RetryResponseVOConverter { | ||||
|     RetryResponseVOConverter INSTANCE = Mappers.getMapper(RetryResponseVOConverter.class); | ||||
| 
 | ||||
|     @Mappings({ | ||||
|             @Mapping(target = "nextTriggerAt", expression = "java(RetryResponseVOConverter.toLocalDateTime(retry.getNextTriggerAt()))"), | ||||
|     }) | ||||
|     RetryResponseVO convert(Retry retry); | ||||
| 
 | ||||
|     static LocalDateTime toLocalDateTime(Long nextTriggerAt) { | ||||
|         if (Objects.isNull(nextTriggerAt) || nextTriggerAt == 0) { | ||||
|             return null; | ||||
|         } | ||||
|         return DateUtils.toLocalDateTime(nextTriggerAt); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| package com.aizuda.snailjob.server.common.vo; | ||||
| 
 | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.Data; | ||||
| 
 | ||||
| @Data | ||||
| public class RequestTriggerRetryVO { | ||||
|     @NotNull(message = "id 不能为空") | ||||
|     private Long id; | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| package com.aizuda.snailjob.server.common.vo; | ||||
| 
 | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.Data; | ||||
| 
 | ||||
| @Data | ||||
| public class RequestUpdateRetryStatusVO { | ||||
|     @NotNull(message = "id 不能为空") | ||||
|     private Long id; | ||||
| 
 | ||||
|     @NotNull(message = "retryStatus 不能为空") | ||||
|     private Integer retryStatus; | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| package com.aizuda.snailjob.server.common.vo; | ||||
| 
 | ||||
| import lombok.Data; | ||||
| 
 | ||||
| import java.time.LocalDateTime; | ||||
| 
 | ||||
| @Data | ||||
| public class RetryResponseVO { | ||||
|     private Long id; | ||||
| 
 | ||||
|     private String namespaceId; | ||||
| 
 | ||||
|     private String groupName; | ||||
| 
 | ||||
|     private String sceneName; | ||||
| 
 | ||||
|     private String idempotentId; | ||||
| 
 | ||||
|     private String bizNo; | ||||
| 
 | ||||
|     private String argsStr; | ||||
| 
 | ||||
|     private String extAttrs; | ||||
| 
 | ||||
|     private String executorName; | ||||
| 
 | ||||
|     /** | ||||
|      * 下次触发时间 | ||||
|      */ | ||||
|     private LocalDateTime nextTriggerAt; | ||||
| 
 | ||||
|     private Integer retryCount; | ||||
| 
 | ||||
|     private Integer retryStatus; | ||||
| 
 | ||||
|     private Integer taskType; | ||||
| 
 | ||||
|     private Long parentId; | ||||
| 
 | ||||
|     private Integer bucketIndex; | ||||
| 
 | ||||
|     private Long deleted; | ||||
| } | ||||
| @ -1,10 +1,9 @@ | ||||
| package com.aizuda.snailjob.server.web.service.convert; | ||||
| package com.aizuda.snailjob.server.retry.task.convert; | ||||
| 
 | ||||
| import com.aizuda.snailjob.server.retry.task.dto.RetryTaskPrepareDTO; | ||||
| import com.aizuda.snailjob.server.retry.task.dto.TaskStopJobDTO; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.Retry; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.Mapping; | ||||
| import org.mapstruct.factory.Mappers; | ||||
| 
 | ||||
| /** | ||||
| @ -0,0 +1,51 @@ | ||||
| package com.aizuda.snailjob.server.retry.task.support.request; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.net.url.UrlQuery; | ||||
| import com.aizuda.snailjob.common.core.constant.SystemConstants; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRequest; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRpcResult; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| import com.aizuda.snailjob.common.log.SnailJobLog; | ||||
| import com.aizuda.snailjob.server.common.convert.RetryResponseVOConverter; | ||||
| import com.aizuda.snailjob.server.common.exception.SnailJobServerException; | ||||
| import com.aizuda.snailjob.server.common.handler.PostHttpRequestHandler; | ||||
| import com.aizuda.snailjob.server.common.vo.RetryResponseVO; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.mapper.RetryMapper; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.Retry; | ||||
| import io.netty.handler.codec.http.HttpHeaders; | ||||
| import io.netty.handler.codec.http.HttpMethod; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| @Component | ||||
| @RequiredArgsConstructor | ||||
| public class OpenApiGetRetryDetailRequestHandler extends PostHttpRequestHandler { | ||||
| 
 | ||||
|     private final RetryMapper retryMapper; | ||||
| 
 | ||||
|     @Override | ||||
|     public SnailJobRpcResult doHandler(String content, UrlQuery query, HttpHeaders headers) { | ||||
|         SnailJobLog.LOCAL.debug("query retry content:[{}]", content); | ||||
|         SnailJobRequest retryRequest = JsonUtil.parseObject(content, SnailJobRequest.class); | ||||
|         Object[] args = retryRequest.getArgs(); | ||||
|         Long retryId = JsonUtil.parseObject(JsonUtil.toJsonString(args[0]), Long.class); | ||||
| 
 | ||||
|         Retry retry = retryMapper.selectById(retryId); | ||||
| 
 | ||||
|         Assert.notNull(retry, () -> new SnailJobServerException("未查询到重试任务:[{}].", retryId)); | ||||
| 
 | ||||
|         RetryResponseVO retryResponseVO = RetryResponseVOConverter.INSTANCE.convert(retry); | ||||
|         return new SnailJobRpcResult(retryResponseVO, retryRequest.getReqId()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean supports(String path) { | ||||
|         return SystemConstants.HTTP_PATH.OPENAPI_ADD_RETRY.equals(path); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public HttpMethod method() { | ||||
|         return HttpMethod.POST; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,83 @@ | ||||
| package com.aizuda.snailjob.server.retry.task.support.request; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.net.url.UrlQuery; | ||||
| import com.aizuda.snailjob.common.core.constant.SystemConstants; | ||||
| import com.aizuda.snailjob.common.core.enums.StatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRequest; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRpcResult; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| import com.aizuda.snailjob.common.log.SnailJobLog; | ||||
| import com.aizuda.snailjob.server.common.enums.RetryTaskExecutorSceneEnum; | ||||
| import com.aizuda.snailjob.server.common.enums.SyetemTaskTypeEnum; | ||||
| import com.aizuda.snailjob.server.common.exception.SnailJobServerException; | ||||
| import com.aizuda.snailjob.server.common.handler.PostHttpRequestHandler; | ||||
| import com.aizuda.snailjob.server.common.pekko.ActorGenerator; | ||||
| import com.aizuda.snailjob.server.common.util.DateUtils; | ||||
| import com.aizuda.snailjob.server.common.vo.RequestTriggerRetryVO; | ||||
| import com.aizuda.snailjob.server.retry.task.convert.RetryConverter; | ||||
| import com.aizuda.snailjob.server.retry.task.dto.RetryTaskPrepareDTO; | ||||
| import com.aizuda.snailjob.template.datasource.access.AccessTemplate; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.mapper.RetryMapper; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.GroupConfig; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.Retry; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import io.netty.handler.codec.http.HttpHeaders; | ||||
| import io.netty.handler.codec.http.HttpMethod; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.apache.pekko.actor.ActorRef; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| @Component | ||||
| @RequiredArgsConstructor | ||||
| public class OpenApiTriggerRetryRequestHandler extends PostHttpRequestHandler { | ||||
| 
 | ||||
|     private final RetryMapper retryMapper; | ||||
| 
 | ||||
|     private final AccessTemplate accessTemplate; | ||||
| 
 | ||||
|     @Override | ||||
|     public SnailJobRpcResult doHandler(String content, UrlQuery query, HttpHeaders headers) { | ||||
|         SnailJobLog.LOCAL.debug("trigger retry:[{}]", content); | ||||
|         SnailJobRequest retryRequest = JsonUtil.parseObject(content, SnailJobRequest.class); | ||||
|         Object[] args = retryRequest.getArgs(); | ||||
|         RequestTriggerRetryVO triggerRetryVO = JsonUtil.parseObject(JsonUtil.toJsonString(args[0]), RequestTriggerRetryVO.class); | ||||
| 
 | ||||
|         Retry retry = retryMapper.selectById(triggerRetryVO.getId()); | ||||
| 
 | ||||
|         Assert.notNull(retry, () -> new SnailJobServerException("未查询到重试任务:[{}].", triggerRetryVO.getId())); | ||||
| 
 | ||||
|         long count = accessTemplate.getGroupConfigAccess().count(new LambdaQueryWrapper<GroupConfig>() | ||||
|                 .eq(GroupConfig::getGroupName, retry.getGroupName()) | ||||
|                 .eq(GroupConfig::getNamespaceId, retry.getNamespaceId()) | ||||
|                 .eq(GroupConfig::getGroupStatus, StatusEnum.YES.getStatus()) | ||||
|         ); | ||||
| 
 | ||||
|         Assert.isTrue(count > 0, () -> new SnailJobServerException("组:[{}]已经关闭,不支持手动执行.", retry.getGroupName())); | ||||
| 
 | ||||
|         Assert.isTrue(Objects.equals(retry.getTaskType(), SyetemTaskTypeEnum.RETRY.getType()), () -> new SnailJobServerException("没有可执行的任务")); | ||||
| 
 | ||||
|         RetryTaskPrepareDTO retryTaskPrepareDTO = RetryConverter.INSTANCE.toRetryTaskPrepareDTO(retry); | ||||
|         // 设置now表示立即执行 | ||||
|         retryTaskPrepareDTO.setNextTriggerAt(DateUtils.toNowMilli()); | ||||
|         retryTaskPrepareDTO.setRetryTaskExecutorScene(RetryTaskExecutorSceneEnum.MANUAL_RETRY.getScene()); | ||||
|         retryTaskPrepareDTO.setRetryId(retry.getId()); | ||||
|         // 准备阶段执行 | ||||
|         ActorRef actorRef = ActorGenerator.retryTaskPrepareActor(); | ||||
|         actorRef.tell(retryTaskPrepareDTO, actorRef); | ||||
|         return new SnailJobRpcResult(true, retryRequest.getReqId()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean supports(String path) { | ||||
|         return SystemConstants.HTTP_PATH.OPENAPI_TRIGGER_RETRY.equals(path); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public HttpMethod method() { | ||||
|         return HttpMethod.POST; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,81 @@ | ||||
| package com.aizuda.snailjob.server.retry.task.support.request; | ||||
| 
 | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.net.url.UrlQuery; | ||||
| import com.aizuda.snailjob.common.core.constant.SystemConstants; | ||||
| import com.aizuda.snailjob.common.core.enums.RetryStatusEnum; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRequest; | ||||
| import com.aizuda.snailjob.common.core.model.SnailJobRpcResult; | ||||
| import com.aizuda.snailjob.common.core.util.JsonUtil; | ||||
| import com.aizuda.snailjob.common.log.SnailJobLog; | ||||
| import com.aizuda.snailjob.server.common.WaitStrategy; | ||||
| import com.aizuda.snailjob.server.common.dto.RetryLogMetaDTO; | ||||
| import com.aizuda.snailjob.server.common.exception.SnailJobServerException; | ||||
| import com.aizuda.snailjob.server.common.handler.PostHttpRequestHandler; | ||||
| import com.aizuda.snailjob.server.common.strategy.WaitStrategies; | ||||
| import com.aizuda.snailjob.server.common.util.DateUtils; | ||||
| import com.aizuda.snailjob.server.common.vo.RequestUpdateRetryStatusVO; | ||||
| import com.aizuda.snailjob.server.retry.task.support.RetryTaskConverter; | ||||
| import com.aizuda.snailjob.template.datasource.access.AccessTemplate; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.mapper.RetryMapper; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.Retry; | ||||
| import com.aizuda.snailjob.template.datasource.persistence.po.RetrySceneConfig; | ||||
| import io.netty.handler.codec.http.HttpHeaders; | ||||
| import io.netty.handler.codec.http.HttpMethod; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import java.time.LocalDateTime; | ||||
| 
 | ||||
| @Component | ||||
| @RequiredArgsConstructor | ||||
| public class OpenApiUpdateRetryStatusRequestHandler extends PostHttpRequestHandler { | ||||
| 
 | ||||
|     private final RetryMapper retryMapper; | ||||
| 
 | ||||
|     private final AccessTemplate accessTemplate; | ||||
| 
 | ||||
|     @Override | ||||
|     public SnailJobRpcResult doHandler(String content, UrlQuery query, HttpHeaders headers) { | ||||
|         SnailJobLog.LOCAL.debug("update retry status:[{}]", content); | ||||
|         SnailJobRequest retryRequest = JsonUtil.parseObject(content, SnailJobRequest.class); | ||||
|         Object[] args = retryRequest.getArgs(); | ||||
|         RequestUpdateRetryStatusVO updateRetryStatusVO = JsonUtil.parseObject(JsonUtil.toJsonString(args[0]), RequestUpdateRetryStatusVO.class); | ||||
| 
 | ||||
|         RetryStatusEnum retryStatusEnum = RetryStatusEnum.getByStatus(updateRetryStatusVO.getRetryStatus()); | ||||
|         Assert.notNull(retryStatusEnum, () -> new SnailJobServerException("重试状态错误. [{}]", updateRetryStatusVO.getRetryStatus())); | ||||
| 
 | ||||
|         Retry retry = retryMapper.selectById(updateRetryStatusVO.getId()); | ||||
|         Assert.notNull(retry, () -> new SnailJobServerException("未查询到重试任务:[{}].", retry.getId())); | ||||
| 
 | ||||
|         retry.setRetryStatus(updateRetryStatusVO.getRetryStatus()); | ||||
| 
 | ||||
|         // 若恢复重试则需要重新计算下次触发时间 | ||||
|         if (RetryStatusEnum.RUNNING == retryStatusEnum) { | ||||
|             RetrySceneConfig retrySceneConfig = accessTemplate.getSceneConfigAccess() | ||||
|                     .getSceneConfigByGroupNameAndSceneName(retry.getGroupName(), retry.getSceneName(), retry.getNamespaceId()); | ||||
|             WaitStrategies.WaitStrategyContext waitStrategyContext = new WaitStrategies.WaitStrategyContext(); | ||||
|             waitStrategyContext.setNextTriggerAt(DateUtils.toNowMilli()); | ||||
|             waitStrategyContext.setTriggerInterval(retrySceneConfig.getTriggerInterval()); | ||||
|             waitStrategyContext.setDelayLevel(retry.getRetryCount() + 1); | ||||
|             WaitStrategy waitStrategy = WaitStrategies.WaitStrategyEnum.getWaitStrategy(retrySceneConfig.getBackOff()); | ||||
|             retry.setNextTriggerAt(waitStrategy.computeTriggerTime(waitStrategyContext)); | ||||
|         } | ||||
| 
 | ||||
|         retry.setUpdateDt(LocalDateTime.now()); | ||||
| 
 | ||||
|         Assert.isTrue(retryMapper.updateById(retry) == 1, () -> new SnailJobServerException("重试任务状态更新失败:[{}].", retry.getId())); | ||||
| 
 | ||||
|         return new SnailJobRpcResult(true, retryRequest.getReqId()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean supports(String path) { | ||||
|         return SystemConstants.HTTP_PATH.OPENAPI_UPDATE_RETRY_STATUS.equals(path); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public HttpMethod method() { | ||||
|         return HttpMethod.POST; | ||||
|     } | ||||
| } | ||||
| @ -35,7 +35,7 @@ import com.aizuda.snailjob.server.web.model.base.PageResult; | ||||
| import com.aizuda.snailjob.server.web.model.request.*; | ||||
| import com.aizuda.snailjob.server.web.model.response.RetryResponseVO; | ||||
| import com.aizuda.snailjob.server.web.service.RetryService; | ||||
| import com.aizuda.snailjob.server.web.service.convert.RetryConverter; | ||||
| import com.aizuda.snailjob.server.retry.task.convert.RetryConverter; | ||||
| import com.aizuda.snailjob.server.web.service.convert.RetryTaskResponseVOConverter; | ||||
| import com.aizuda.snailjob.server.web.service.convert.TaskContextConverter; | ||||
| import com.aizuda.snailjob.server.web.util.UserSessionUtils; | ||||
|  | ||||
| @ -18,7 +18,7 @@ import com.aizuda.snailjob.server.web.model.request.UserSessionVO; | ||||
| import com.aizuda.snailjob.server.web.model.response.RetryTaskLogMessageResponseVO; | ||||
| import com.aizuda.snailjob.server.web.model.response.RetryTaskResponseVO; | ||||
| import com.aizuda.snailjob.server.web.service.RetryTaskService; | ||||
| import com.aizuda.snailjob.server.web.service.convert.RetryConverter; | ||||
| import com.aizuda.snailjob.server.retry.task.convert.RetryConverter; | ||||
| import com.aizuda.snailjob.server.web.service.convert.RetryTaskLogResponseVOConverter; | ||||
| import com.aizuda.snailjob.server.web.service.convert.RetryTaskResponseVOConverter; | ||||
| import com.aizuda.snailjob.server.web.util.UserSessionUtils; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 xiaochaihu
						xiaochaihu