From 018357cadad5ea9547c235285c263e2acd9d41ce Mon Sep 17 00:00:00 2001
From: byteblogs168 <598092184@qq.com>
Date: Sun, 16 Jul 2023 22:58:54 +0800
Subject: [PATCH] =?UTF-8?q?feat:=202.1.0=201.=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E9=80=9A=E8=BF=87=E6=8E=A7=E5=88=B6=E5=8F=B0=E8=A7=A3=E6=9E=90?=
=?UTF-8?q?=E6=97=A5=E5=BF=97=E9=A1=B5=E9=9D=A2=202.=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=97=A5=E5=BF=97=E8=A7=A3=E6=9E=90=E5=92=8C?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BB=BB=E5=8A=A1=203.=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E4=BA=86=E6=96=B0=E5=A2=9E=E4=BB=BB=E5=8A=A1=E6=A8=A1=E5=9E=8B?=
=?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E5=AE=A2=E6=88=B7=E7=AB=AF=E4=B8=8A?=
=?UTF-8?q?=E6=8A=A5=E3=80=81=E6=8E=A7=E5=88=B6=E5=8F=B0=E6=89=8B=E5=8A=A8?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=92=8C=E5=8D=95=E4=B8=AA=E6=96=B0=E5=A2=9E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../annotation/ExecutorMethodRegister.java | 7 +-
.../retry/client/core/annotation/Mapping.java | 6 +
.../client/core/annotation/Retryable.java | 6 +-
.../core/client/netty/NettyChannel.java | 2 +-
.../client/core/report/ReportListener.java | 16 +-
.../strategy/AbstractRetryStrategies.java | 12 +-
.../retry/server/model/dto/RetryTaskDTO.java | 2 +-
easy-retry-server/pom.xml | 6 +
.../server/enums/TaskGeneratorScene.java | 37 ++++
.../mybatis/mapper/RetryTaskLogMapper.java | 2 +
.../mybatis/mapper/RetryTaskMapper.java | 2 +
.../persistence/support/ConfigAccess.java | 2 +-
.../ReportRetryInfoHttpRequestHandler.java | 45 +++-
.../server/service/RetryTaskService.java | 14 +-
.../service/convert/RetryTaskConverter.java | 3 +
.../service/convert/TaskContextConverter.java | 23 +++
.../server/service/impl/RetryServiceImpl.java | 2 +-
.../service/impl/RetryTaskServiceImpl.java | 96 ++++++---
.../support/generator/TaskGenerator.java | 29 +++
.../generator/task/AbstractGenerator.java | 195 ++++++++++++++++++
.../task/ClientReportRetryGenerator.java | 19 ++
.../task/ManaBatchRetryGenerator.java | 19 ++
.../task/ManaSingleRetryGenerator.java | 19 ++
.../support/generator/task/TaskContext.java | 57 +++++
.../web/controller/RetryTaskController.java | 13 +-
.../server/web/model/request/ParseLogsVO.java | 37 ++++
.../resources/mapper/RetryTaskLogMapper.xml | 9 +
.../main/resources/mapper/RetryTaskMapper.xml | 8 +
frontend/src/api/manage.js | 9 +
frontend/src/views/task/RetryTaskList.vue | 12 +-
.../views/task/form/BatchSaveRetryTask.vue | 128 ++++++++++++
31 files changed, 763 insertions(+), 74 deletions(-)
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/enums/TaskGeneratorScene.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/TaskContextConverter.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/TaskGenerator.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/AbstractGenerator.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ClientReportRetryGenerator.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaBatchRetryGenerator.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaSingleRetryGenerator.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/TaskContext.java
create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/model/request/ParseLogsVO.java
create mode 100644 frontend/src/views/task/form/BatchSaveRetryTask.vue
diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/ExecutorMethodRegister.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/ExecutorMethodRegister.java
index 90ce8a30..414dca03 100644
--- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/ExecutorMethodRegister.java
+++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/ExecutorMethodRegister.java
@@ -44,7 +44,7 @@ public @interface ExecutorMethodRegister {
* 时刻3: 上报一个异常 idempotentId: A1 不会新增一个重试任务,会被幂等处理
* 时刻4: idempotentId: A1 重试完成, 状态为已完成
* 时刻5: 上报一个异常 idempotentId: A1 状态为重试中, 新增一条重试任务
- **
+ *
* 默认的idempotentId生成器{@link SimpleIdempotentIdGenerate} 对所有参数进行MD5
*
* @return idempotentId
@@ -54,14 +54,13 @@ public @interface ExecutorMethodRegister {
/**
* 服务端重试完成(重试成功、重试到达最大次数)回调客户端
*
- * @return
*/
Class extends RetryCompleteCallback> retryCompleteCallback() default SimpleRetryCompleteCallback.class;
/**
* 用于标识具有业务特点的值, 比如订单号、物流编号等,可以根据具体的业务场景生成,生成规则采用通用成熟的Spel表达式进行解析
- *
- * see: https://docs.spring.io/spring-framework/docs/5.0.0.M5/spring-framework-reference/html/expressions.html
+ *
+ * see: ...
*/
String bizNo() default "";
diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Mapping.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Mapping.java
index 102cf478..4ea8fe16 100644
--- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Mapping.java
+++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Mapping.java
@@ -20,8 +20,14 @@ import java.lang.annotation.Target;
@Documented
public @interface Mapping {
+ /**
+ * 请求类型
+ */
RequestMethod method() default RequestMethod.GET;
+ /**
+ * 请求路径
+ */
String path() default "";
}
diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Retryable.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Retryable.java
index a118bb69..996d8039 100644
--- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Retryable.java
+++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/annotation/Retryable.java
@@ -45,7 +45,6 @@ public @interface Retryable {
/**
* 重试处理入口,默认为原方法
*
- * @return
*/
Class extends ExecutorMethod> retryMethod() default ExecutorAnnotationMethod.class;
@@ -60,7 +59,7 @@ public @interface Retryable {
* 时刻3: 上报一个异常 idempotentId: A1 不会新增一个重试任务,会被幂等处理
* 时刻4: idempotentId: A1 重试完成, 状态为已完成
* 时刻5: 上报一个异常 idempotentId: A1 状态为重试中, 新增一条重试任务
- **
+ *
* 默认的idempotentId生成器{@link SimpleIdempotentIdGenerate} 对所有参数进行MD5
*
* @return idempotentId
@@ -70,14 +69,13 @@ public @interface Retryable {
/**
* 服务端重试完成(重试成功、重试到达最大次数)回调客户端
*
- * @return
*/
Class extends RetryCompleteCallback> retryCompleteCallback() default SimpleRetryCompleteCallback.class;
/**
* 用于标识具有业务特点的值, 比如订单号、物流编号等,可以根据具体的业务场景生成,生成规则采用通用成熟的Spel表达式进行解析
*
- * see: https://docs.spring.io/spring-framework/docs/5.0.0.M5/spring-framework-reference/html/expressions.html
+ * see: ...
*/
String bizNo() default "";
diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/client/netty/NettyChannel.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/client/netty/NettyChannel.java
index 7443e7b5..5ecca028 100644
--- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/client/netty/NettyChannel.java
+++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/client/netty/NettyChannel.java
@@ -50,7 +50,7 @@ public class NettyChannel {
public static void send(HttpMethod method, String url, String body) throws InterruptedException {
if (Objects.isNull(CHANNEL)) {
- LogUtils.info(log, "send message but channel is null url:[{}] method:[{}] body:[{}] ", url, method, body);
+ LogUtils.error(log, "send message but channel is null url:[{}] method:[{}] body:[{}] ", url, method, body);
return;
}
diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/report/ReportListener.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/report/ReportListener.java
index e477a108..25b2f90c 100644
--- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/report/ReportListener.java
+++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/report/ReportListener.java
@@ -2,13 +2,10 @@ package com.aizuda.easy.retry.client.core.report;
import com.aizuda.easy.retry.client.core.RetryExecutor;
import com.aizuda.easy.retry.client.core.RetryExecutorParameter;
+import com.aizuda.easy.retry.client.core.cache.GroupVersionCache;
import com.aizuda.easy.retry.client.core.client.NettyClient;
import com.aizuda.easy.retry.client.core.client.proxy.RequestBuilder;
import com.aizuda.easy.retry.client.core.config.EasyRetryProperties;
-import com.aizuda.easy.retry.common.core.model.NettyResult;
-import com.github.rholder.retry.*;
-import com.google.common.base.Predicate;
-import com.aizuda.easy.retry.client.core.cache.GroupVersionCache;
import com.aizuda.easy.retry.client.core.executor.GuavaRetryExecutor;
import com.aizuda.easy.retry.common.core.alarm.Alarm;
import com.aizuda.easy.retry.common.core.alarm.AlarmContext;
@@ -16,11 +13,13 @@ import com.aizuda.easy.retry.common.core.alarm.EasyRetryAlarmFactory;
import com.aizuda.easy.retry.common.core.context.SpringContext;
import com.aizuda.easy.retry.common.core.enums.NotifySceneEnum;
import com.aizuda.easy.retry.common.core.log.LogUtils;
+import com.aizuda.easy.retry.common.core.model.NettyResult;
import com.aizuda.easy.retry.common.core.util.EnvironmentUtils;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
import com.aizuda.easy.retry.common.core.window.Listener;
import com.aizuda.easy.retry.server.model.dto.ConfigDTO;
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
+import com.github.rholder.retry.*;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
@@ -61,13 +60,13 @@ public class ReportListener implements Listener {
try {
retryExecutor.call(retryer, () -> {
- LogUtils.info(log, "Batch asynchronous reporting ...");
+ LogUtils.info(log, "Batch asynchronous reporting ... <|>{}<|>", JsonUtil.toJsonString(list));
CLIENT.reportRetryInfo(list);
return null;
}, throwable -> {
- LogUtils.info(log,"Data report failed:{}", JsonUtil.toJsonString(list));
+ LogUtils.error(log,"Data report failed. <|>{}<|>", JsonUtil.toJsonString(list));
sendMessage(throwable);
- }, o -> LogUtils.info(log,"Data report successful retry:{}", JsonUtil.toJsonString(list)));
+ }, o -> LogUtils.info(log,"Data report successful retry:<|>{}<|>", JsonUtil.toJsonString(list)));
} catch (Exception e) {
e.printStackTrace();
}
@@ -91,9 +90,6 @@ public class ReportListener implements Listener {
return Collections.singletonList(new RetryListener() {
@Override
public void onRetry(Attempt attempt) {
- if (attempt.hasResult()) {
- LogUtils.error(log,"easy-retry 上报成功,第[{}]次调度", attempt.getAttemptNumber());
- }
if (attempt.hasException()) {
LogUtils.error(log,"easy-retry 上报失败,第[{}]次调度 ", attempt.getAttemptNumber(), attempt.getExceptionCause());
diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/AbstractRetryStrategies.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/AbstractRetryStrategies.java
index 851d209d..9c8fb507 100644
--- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/AbstractRetryStrategies.java
+++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/AbstractRetryStrategies.java
@@ -56,8 +56,8 @@ public abstract class AbstractRetryStrategies implements RetryStrategy {
retryerResultContext.setRetryerInfo(retryerInfo);
try {
- for (EasyRetryListener EasyRetryListener : easyRetryListeners) {
- EasyRetryListener.beforeRetry(sceneName, executorClassName, params);
+ for (EasyRetryListener easyRetryListener : easyRetryListeners) {
+ easyRetryListener.beforeRetry(sceneName, executorClassName, params);
}
Object result = retryExecutor.call(retryer, doGetCallable(retryExecutor, params), getRetryErrorConsumer(retryerResultContext, params), getRetrySuccessConsumer(retryerResultContext));
@@ -83,8 +83,8 @@ public abstract class AbstractRetryStrategies implements RetryStrategy {
Object result = retryerResultContext.getResult();
RetryerInfo retryerInfo = retryerResultContext.getRetryerInfo();
- for (EasyRetryListener EasyRetryListener : easyRetryListeners) {
- EasyRetryListener.successOnRetry(result, retryerInfo.getScene(), retryerInfo.getExecutorClassName());
+ for (EasyRetryListener easyRetryListener : easyRetryListeners) {
+ easyRetryListener.successOnRetry(result, retryerInfo.getScene(), retryerInfo.getExecutorClassName());
}
doRetrySuccessConsumer(retryerResultContext).accept(retryerResultContext);
@@ -103,8 +103,8 @@ public abstract class AbstractRetryStrategies implements RetryStrategy {
RetryerInfo retryerInfo = context.getRetryerInfo();
try {
- for (EasyRetryListener EasyRetryListener : easyRetryListeners) {
- EasyRetryListener
+ for (EasyRetryListener easyRetryListener : easyRetryListeners) {
+ easyRetryListener
.failureOnRetry(retryerInfo.getScene(), retryerInfo.getExecutorClassName(), throwable);
}
} catch (Exception e) {
diff --git a/easy-retry-common/easy-retry-common-server-api/src/main/java/com/aizuda/easy/retry/server/model/dto/RetryTaskDTO.java b/easy-retry-common/easy-retry-common-server-api/src/main/java/com/aizuda/easy/retry/server/model/dto/RetryTaskDTO.java
index 77df9a54..94ff6bd3 100644
--- a/easy-retry-common/easy-retry-common-server-api/src/main/java/com/aizuda/easy/retry/server/model/dto/RetryTaskDTO.java
+++ b/easy-retry-common/easy-retry-common-server-api/src/main/java/com/aizuda/easy/retry/server/model/dto/RetryTaskDTO.java
@@ -18,7 +18,7 @@ public class RetryTaskDTO implements Serializable {
/**
* 加密的groupId
*/
- @NotBlank(message = "shardingGroupId 不能为空")
+ @NotBlank(message = "groupName 不能为空")
@Length(max = 16, message = "组id最长为16")
private String groupName;
diff --git a/easy-retry-server/pom.xml b/easy-retry-server/pom.xml
index ba1906ac..716fcf4e 100644
--- a/easy-retry-server/pom.xml
+++ b/easy-retry-server/pom.xml
@@ -137,6 +137,12 @@
org.hibernate
hibernate-validator
+
+ org.jetbrains
+ annotations
+ 13.0
+ compile
+
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/enums/TaskGeneratorScene.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/enums/TaskGeneratorScene.java
new file mode 100644
index 00000000..5b16e910
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/enums/TaskGeneratorScene.java
@@ -0,0 +1,37 @@
+package com.aizuda.easy.retry.server.enums;
+
+import com.aizuda.easy.retry.server.exception.EasyRetryServerException;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * id生成模式
+ *
+ * @author www.byteblogs.com
+ * @date 2023-05-04
+ * @since 2.0
+ */
+@AllArgsConstructor
+@Getter
+public enum TaskGeneratorScene {
+
+ CLIENT_REPORT(1,"客户端匹配上报"),
+ MANA_BATCH(2, "控制台手动批量新增"),
+ MANA_SINGLE(3, "控制台手动单个新增"),
+ ;
+
+ private final int scene;
+
+ private final String desc;
+
+ public static TaskGeneratorScene modeOf(int scene) {
+ for (TaskGeneratorScene value : TaskGeneratorScene.values()) {
+ if (value.getScene() == scene) {
+ return value;
+ }
+ }
+
+ throw new EasyRetryServerException("不支持的任务生成场景 [{}]", scene);
+ }
+
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskLogMapper.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskLogMapper.java
index 6696474e..528dacf8 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskLogMapper.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskLogMapper.java
@@ -30,4 +30,6 @@ public interface RetryTaskLogMapper extends BaseMapper {
@Param("endTime")LocalDateTime endTime
);
+ int batchInsert(List list);
+
}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskMapper.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskMapper.java
index a5b25e6e..63999190 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskMapper.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/mybatis/mapper/RetryTaskMapper.java
@@ -13,4 +13,6 @@ public interface RetryTaskMapper extends BaseMapper {
int countAllRetryTaskByRetryStatus(@Param("partition") Integer partition,
@Param("retryStatus") Integer retryStatus);
+ int batchInsert(List list);
+
}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/support/ConfigAccess.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/support/ConfigAccess.java
index 4f8a9353..a31c7043 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/support/ConfigAccess.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/persistence/support/ConfigAccess.java
@@ -76,7 +76,7 @@ public interface ConfigAccess {
*
* @return 黑名单列表
*/
- Set getBlacklist(String shardingGroupId);
+ Set getBlacklist(String groupName);
/**
* 获取所有组配置信息
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/server/handler/ReportRetryInfoHttpRequestHandler.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/server/handler/ReportRetryInfoHttpRequestHandler.java
index 3b1aada7..efca0c0a 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/server/handler/ReportRetryInfoHttpRequestHandler.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/server/handler/ReportRetryInfoHttpRequestHandler.java
@@ -1,6 +1,9 @@
package com.aizuda.easy.retry.server.server.handler;
+import cn.hutool.core.lang.Assert;
import cn.hutool.core.net.url.UrlQuery;
+import com.aizuda.easy.retry.server.enums.TaskGeneratorScene;
+import com.aizuda.easy.retry.server.exception.EasyRetryServerException;
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
import com.aizuda.easy.retry.server.service.RetryService;
import com.aizuda.easy.retry.server.enums.StatusEnum;
@@ -8,12 +11,20 @@ import com.aizuda.easy.retry.common.core.log.LogUtils;
import com.aizuda.easy.retry.common.core.model.NettyResult;
import com.aizuda.easy.retry.common.core.model.EasyRetryRequest;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
+import com.aizuda.easy.retry.server.service.convert.TaskContextConverter;
+import com.aizuda.easy.retry.server.support.generator.TaskGenerator;
+import com.aizuda.easy.retry.server.support.generator.task.TaskContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
import static com.aizuda.easy.retry.common.core.constant.SystemConstants.HTTP_PATH.BATCH_REPORT;
/**
@@ -28,7 +39,7 @@ import static com.aizuda.easy.retry.common.core.constant.SystemConstants.HTTP_PA
public class ReportRetryInfoHttpRequestHandler extends PostHttpRequestHandler {
@Autowired
- private RetryService retryService;
+ private List taskGenerators;
@Override
public boolean supports(String path) {
@@ -42,18 +53,38 @@ public class ReportRetryInfoHttpRequestHandler extends PostHttpRequestHandler {
@Override
public String doHandler(String content, UrlQuery urlQuery, HttpHeaders headers) {
- LogUtils.info(log, "批量上报重试数据 content:[{}]", content);
+ LogUtils.info(log, "Batch Report Retry Data. content:[{}]", content);
EasyRetryRequest retryRequest = JsonUtil.parseObject(content, EasyRetryRequest.class);
+ Object[] args = retryRequest.getArgs();
try {
- Object[] args = retryRequest.getArgs();
+ TaskGenerator taskGenerator = taskGenerators.stream()
+ .filter(t -> t.supports(TaskGeneratorScene.CLIENT_REPORT.getScene()))
+ .findFirst().orElseThrow(() -> new EasyRetryServerException("没有匹配的任务生成器"));
- Boolean aBoolean = retryService.batchReportRetry(JsonUtil.parseList(JsonUtil.toJsonString(args[0]), RetryTaskDTO.class));
- return JsonUtil.toJsonString(new NettyResult(StatusEnum.YES.getStatus(), "批量上报重试数据处理成功", aBoolean, retryRequest.getReqId()));
+ Assert.notEmpty(args, () -> new EasyRetryServerException("上报的数据不能为空. reqId:[{}]", retryRequest.getReqId()));
+ List retryTaskList = JsonUtil.parseList(JsonUtil.toJsonString(args[0]), RetryTaskDTO.class);
+
+ Set set = retryTaskList.stream().map(RetryTaskDTO::getGroupName).collect(Collectors.toSet());
+ Assert.isTrue(set.size() <= 1, () -> new EasyRetryServerException("批量上报数据,同一批次只能是相同的组. reqId:[{}]", retryRequest.getReqId()));
+
+ Map> map = retryTaskList.stream().collect(Collectors.groupingBy(RetryTaskDTO::getSceneName));
+
+ map.forEach(((sceneName, retryTaskDTOS) -> {
+ TaskContext taskContext = new TaskContext();
+ taskContext.setSceneName(sceneName);
+ taskContext.setGroupName(set.stream().findFirst().get());
+ taskContext.setTaskInfos(TaskContextConverter.INSTANCE.toTaskContextInfo(retryTaskList));
+
+ // 生成任务
+ taskGenerator.taskGenerator(taskContext);
+ }));
+
+ return JsonUtil.toJsonString(new NettyResult(StatusEnum.YES.getStatus(), "Batch Retry Data Upload Processed Successfully", Boolean.TRUE, retryRequest.getReqId()));
} catch (Exception e) {
- LogUtils.error(log, "批量上报重试数据失败", e);
- return JsonUtil.toJsonString(new NettyResult(StatusEnum.YES.getStatus(), e.getMessage(), null, retryRequest.getReqId()));
+ LogUtils.error(log, "Batch Report Retry Data Error. <|>{}<|>", args[0], e);
+ return JsonUtil.toJsonString(new NettyResult(StatusEnum.YES.getStatus(), e.getMessage(), Boolean.FALSE, retryRequest.getReqId()));
}
}
}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/RetryTaskService.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/RetryTaskService.java
index 6b37fe0a..8010590c 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/RetryTaskService.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/RetryTaskService.java
@@ -1,12 +1,7 @@
package com.aizuda.easy.retry.server.service;
import com.aizuda.easy.retry.server.web.model.base.PageResult;
-import com.aizuda.easy.retry.server.web.model.request.BatchDeleteRetryTaskVO;
-import com.aizuda.easy.retry.server.web.model.request.GenerateRetryIdempotentIdVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskQueryVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskUpdateStatusRequestVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskSaveRequestVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskUpdateExecutorNameRequestVO;
+import com.aizuda.easy.retry.server.web.model.request.*;
import com.aizuda.easy.retry.server.web.model.response.RetryTaskResponseVO;
import java.util.List;
@@ -69,4 +64,11 @@ public interface RetryTaskService {
*/
Integer deleteRetryTask(BatchDeleteRetryTaskVO requestVO);
+ /**
+ * 解析日志
+ *
+ * @param parseLogsVO {@link ParseLogsVO} 解析参数模型
+ * @return
+ */
+ Integer parseLogs(ParseLogsVO parseLogsVO);
}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/RetryTaskConverter.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/RetryTaskConverter.java
index bbcef684..8b65e6c5 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/RetryTaskConverter.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/RetryTaskConverter.java
@@ -3,6 +3,7 @@ package com.aizuda.easy.retry.server.service.convert;
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryDeadLetter;
import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryTask;
+import com.aizuda.easy.retry.server.support.generator.task.TaskContext;
import com.aizuda.easy.retry.server.web.model.request.RetryTaskSaveRequestVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@@ -32,4 +33,6 @@ public interface RetryTaskConverter {
RetryTask toRetryTask(RetryTaskSaveRequestVO retryTaskSaveRequestVO);
List toRetryTaskList(List retryTaskDTOList);
+
+ RetryTask toRetryTask(TaskContext.TaskInfo taskInfo);
}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/TaskContextConverter.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/TaskContextConverter.java
new file mode 100644
index 00000000..1d066082
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/convert/TaskContextConverter.java
@@ -0,0 +1,23 @@
+package com.aizuda.easy.retry.server.service.convert;
+
+import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
+import com.aizuda.easy.retry.server.support.generator.task.TaskContext;
+import com.aizuda.easy.retry.server.web.model.request.RetryTaskSaveRequestVO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * @author www.byteblogs.com
+ * @date 2023-07-16 22:09:40
+ * @since 2.1.0
+ */
+@Mapper
+public interface TaskContextConverter {
+ TaskContextConverter INSTANCE = Mappers.getMapper(TaskContextConverter.class);
+
+ TaskContext.TaskInfo toTaskContextInfo(RetryTaskSaveRequestVO retryTaskSaveRequestVO);
+
+ List toTaskContextInfo(List retryTasks);
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryServiceImpl.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryServiceImpl.java
index 9223c074..dd5e7e38 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryServiceImpl.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryServiceImpl.java
@@ -74,7 +74,7 @@ public class RetryServiceImpl implements RetryService {
@Transactional
@Override
public Boolean reportRetry(RetryTaskDTO retryTaskDTO) {
- LogUtils.warn(log, "received report data [{}]", JsonUtil.toJsonString(retryTaskDTO));
+ LogUtils.info(log, "received report data. <|>{}<|>", JsonUtil.toJsonString(retryTaskDTO));
SceneConfig sceneConfig = configAccess.getSceneConfigByGroupNameAndSceneName(retryTaskDTO.getGroupName(), retryTaskDTO.getSceneName());
if (Objects.isNull(sceneConfig)) {
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryTaskServiceImpl.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryTaskServiceImpl.java
index 89971ff9..bb49ea04 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryTaskServiceImpl.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/service/impl/RetryTaskServiceImpl.java
@@ -5,10 +5,13 @@ import cn.hutool.core.lang.Assert;
import com.aizuda.easy.retry.client.model.GenerateRetryIdempotentIdDTO;
import com.aizuda.easy.retry.common.core.enums.RetryStatusEnum;
import com.aizuda.easy.retry.common.core.model.Result;
+import com.aizuda.easy.retry.common.core.util.JsonUtil;
import com.aizuda.easy.retry.server.akka.ActorGenerator;
import com.aizuda.easy.retry.server.config.RequestDataHelper;
import com.aizuda.easy.retry.server.dto.RegisterNodeInfo;
+import com.aizuda.easy.retry.server.enums.TaskGeneratorScene;
import com.aizuda.easy.retry.server.exception.EasyRetryServerException;
+import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
import com.aizuda.easy.retry.server.persistence.mybatis.mapper.RetryTaskLogMapper;
import com.aizuda.easy.retry.server.persistence.mybatis.mapper.RetryTaskLogMessageMapper;
import com.aizuda.easy.retry.server.persistence.mybatis.mapper.RetryTaskMapper;
@@ -21,17 +24,15 @@ import com.aizuda.easy.retry.server.persistence.support.ConfigAccess;
import com.aizuda.easy.retry.server.service.RetryTaskService;
import com.aizuda.easy.retry.server.service.convert.RetryTaskConverter;
import com.aizuda.easy.retry.server.service.convert.RetryTaskResponseVOConverter;
+import com.aizuda.easy.retry.server.service.convert.TaskContextConverter;
import com.aizuda.easy.retry.server.support.dispatch.actor.log.RetryTaskLogDTO;
import com.aizuda.easy.retry.server.support.generator.IdGenerator;
+import com.aizuda.easy.retry.server.support.generator.TaskGenerator;
+import com.aizuda.easy.retry.server.support.generator.task.TaskContext;
import com.aizuda.easy.retry.server.support.handler.ClientNodeAllocateHandler;
import com.aizuda.easy.retry.server.support.strategy.WaitStrategies;
import com.aizuda.easy.retry.server.web.model.base.PageResult;
-import com.aizuda.easy.retry.server.web.model.request.BatchDeleteRetryTaskVO;
-import com.aizuda.easy.retry.server.web.model.request.GenerateRetryIdempotentIdVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskQueryVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskUpdateStatusRequestVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskSaveRequestVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskUpdateExecutorNameRequestVO;
+import com.aizuda.easy.retry.server.web.model.request.*;
import com.aizuda.easy.retry.server.web.model.response.RetryTaskResponseVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -42,14 +43,16 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.text.MessageFormat;
import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* @author www.byteblogs.com
@@ -76,6 +79,8 @@ public class RetryTaskServiceImpl implements RetryTaskService {
@Autowired
@Qualifier("configAccessProcessor")
private ConfigAccess configAccess;
+ @Autowired
+ private List taskGenerators;
@Override
public PageResult> getRetryTaskPage(RetryTaskQueryVO queryVO) {
@@ -109,8 +114,8 @@ public class RetryTaskServiceImpl implements RetryTaskService {
RequestDataHelper.setPartition(queryVO.getGroupName());
retryTaskLambdaQueryWrapper.select(RetryTask::getId, RetryTask::getBizNo, RetryTask::getIdempotentId,
- RetryTask::getGroupName, RetryTask::getNextTriggerAt, RetryTask::getRetryCount,
- RetryTask::getRetryStatus, RetryTask::getUpdateDt, RetryTask::getSceneName, RetryTask::getUniqueId, RetryTask::getTaskType);
+ RetryTask::getGroupName, RetryTask::getNextTriggerAt, RetryTask::getRetryCount,
+ RetryTask::getRetryStatus, RetryTask::getUpdateDt, RetryTask::getSceneName, RetryTask::getUniqueId, RetryTask::getTaskType);
pageDTO = retryTaskMapper.selectPage(pageDTO, retryTaskLambdaQueryWrapper.orderByDesc(RetryTask::getCreateDt));
return new PageResult<>(pageDTO, RetryTaskResponseVOConverter.INSTANCE.toRetryTaskResponseVO(pageDTO.getRecords()));
}
@@ -142,7 +147,7 @@ public class RetryTaskServiceImpl implements RetryTaskService {
// 若恢复重试则需要重新计算下次触发时间
if (RetryStatusEnum.RUNNING.getStatus().equals(retryStatusEnum.getStatus())) {
retryTask.setNextTriggerAt(
- WaitStrategies.randomWait(1, TimeUnit.SECONDS, 60, TimeUnit.SECONDS).computeRetryTime(null));
+ WaitStrategies.randomWait(1, TimeUnit.SECONDS, 60, TimeUnit.SECONDS).computeRetryTime(null));
}
if (RetryStatusEnum.FINISH.getStatus().equals(retryStatusEnum.getStatus())) {
@@ -172,19 +177,19 @@ public class RetryTaskServiceImpl implements RetryTaskService {
throw new EasyRetryServerException("重试状态错误");
}
- RetryTask retryTask = RetryTaskConverter.INSTANCE.toRetryTask(retryTaskRequestVO);
- retryTask.setCreateDt(LocalDateTime.now());
- retryTask.setUpdateDt(LocalDateTime.now());
+ TaskGenerator taskGenerator = taskGenerators.stream()
+ .filter(t -> t.supports(TaskGeneratorScene.MANA_SINGLE.getScene()))
+ .findFirst().orElseThrow(() -> new EasyRetryServerException("没有匹配的任务生成器"));
- if (StringUtils.isBlank(retryTask.getExtAttrs())) {
- retryTask.setExtAttrs(StringUtils.EMPTY);
- }
+ TaskContext taskContext = new TaskContext();
+ taskContext.setSceneName(retryTaskRequestVO.getSceneName());
+ taskContext.setGroupName(retryTaskRequestVO.getGroupName());
+ taskContext.setTaskInfos(Collections.singletonList(TaskContextConverter.INSTANCE.toTaskContextInfo(retryTaskRequestVO)));
- retryTask.setNextTriggerAt(
- WaitStrategies.randomWait(1, TimeUnit.SECONDS, 60, TimeUnit.SECONDS).computeRetryTime(null));
- retryTask.setUniqueId(getIdGenerator(retryTask.getGroupName()));
- RequestDataHelper.setPartition(retryTaskRequestVO.getGroupName());
- return retryTaskMapper.insert(retryTask);
+ // 生成任务
+ taskGenerator.taskGenerator(taskContext);
+
+ return 1;
}
@Override
@@ -194,7 +199,7 @@ public class RetryTaskServiceImpl implements RetryTaskService {
// 委托客户端生成idempotentId
String url = MessageFormat
- .format(URL, serverNode.getHostIp(), serverNode.getHostPort().toString(), serverNode.getContextPath());
+ .format(URL, serverNode.getHostIp(), serverNode.getHostPort().toString(), serverNode.getContextPath());
GenerateRetryIdempotentIdDTO generateRetryIdempotentIdDTO = new GenerateRetryIdempotentIdDTO();
generateRetryIdempotentIdDTO.setGroup(generateRetryIdempotentIdVO.getGroupName());
@@ -222,7 +227,7 @@ public class RetryTaskServiceImpl implements RetryTaskService {
// 根据重试数据id,更新执行器名称
RequestDataHelper.setPartition(requestVO.getGroupName());
return retryTaskMapper
- .update(retryTask, new LambdaUpdateWrapper().in(RetryTask::getId, requestVO.getIds()));
+ .update(retryTask, new LambdaUpdateWrapper().in(RetryTask::getId, requestVO.getIds()));
}
@Override
@@ -231,6 +236,47 @@ public class RetryTaskServiceImpl implements RetryTaskService {
return retryTaskMapper.deleteBatchIds(requestVO.getIds());
}
+ @Override
+ public Integer parseLogs(ParseLogsVO parseLogsVO) {
+
+ String logStr = parseLogsVO.getLogStr();
+
+ String patternString = "<\\|>(.*?)<\\|>";
+ Pattern pattern = Pattern.compile(patternString);
+ Matcher matcher = pattern.matcher(logStr);
+
+ List waitInsertList = new ArrayList<>();
+ // 查找匹配的内容并输出
+ while (matcher.find()) {
+ String extractedData = matcher.group(1);
+ if (StringUtils.isBlank(extractedData)) {
+ continue;
+ }
+
+ List retryTaskList = JsonUtil.parseList(extractedData, RetryTaskDTO.class);
+ if (!CollectionUtils.isEmpty(retryTaskList)) {
+ waitInsertList.addAll(retryTaskList);
+ }
+ }
+
+ Assert.isFalse(waitInsertList.isEmpty(), () -> new EasyRetryServerException("未找到匹配的数据"));
+ Assert.isTrue(waitInsertList.size() <= 500, () -> new EasyRetryServerException("最多只能处理500条数据"));
+
+ TaskGenerator taskGenerator = taskGenerators.stream()
+ .filter(t -> t.supports(TaskGeneratorScene.MANA_BATCH.getScene()))
+ .findFirst().orElseThrow(() -> new EasyRetryServerException("没有匹配的任务生成器"));
+
+ TaskContext taskContext = new TaskContext();
+ taskContext.setSceneName(parseLogsVO.getSceneName());
+ taskContext.setGroupName(parseLogsVO.getGroupName());
+ taskContext.setTaskInfos(TaskContextConverter.INSTANCE.toTaskContextInfo(waitInsertList));
+
+ // 生成任务
+ taskGenerator.taskGenerator(taskContext);
+
+ return waitInsertList.size();
+ }
+
/**
* 获取分布式id
*
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/TaskGenerator.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/TaskGenerator.java
new file mode 100644
index 00000000..a4cea93b
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/TaskGenerator.java
@@ -0,0 +1,29 @@
+package com.aizuda.easy.retry.server.support.generator;
+
+import com.aizuda.easy.retry.server.support.generator.task.TaskContext;
+
+/**
+ * 任务生成器
+ *
+ * @author www.byteblogs.com
+ * @date 2023-07-16 11:42:38
+ * @since 2.1.0
+ */
+public interface TaskGenerator {
+
+ /**
+ * 获取匹配的模式
+ *
+ * @param scene 1. 客户端上报 2.控制台新增单个任务 3.控制台批量新增任务
+ * @return 符合条件的生成器
+ */
+ boolean supports(int scene);
+
+ /**
+ * 任务生成器
+ *
+ * @param taskContext 任务列表
+ * @return 成功处理的数据量
+ */
+ void taskGenerator(TaskContext taskContext);
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/AbstractGenerator.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/AbstractGenerator.java
new file mode 100644
index 00000000..195f0874
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/AbstractGenerator.java
@@ -0,0 +1,195 @@
+package com.aizuda.easy.retry.server.support.generator.task;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.lang.Pair;
+import com.aizuda.easy.retry.common.core.log.LogUtils;
+import com.aizuda.easy.retry.common.core.util.JsonUtil;
+import com.aizuda.easy.retry.server.config.RequestDataHelper;
+import com.aizuda.easy.retry.server.enums.DelayLevelEnum;
+import com.aizuda.easy.retry.server.enums.StatusEnum;
+import com.aizuda.easy.retry.server.enums.TaskTypeEnum;
+import com.aizuda.easy.retry.server.exception.EasyRetryServerException;
+import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
+import com.aizuda.easy.retry.server.persistence.mybatis.mapper.*;
+import com.aizuda.easy.retry.server.persistence.mybatis.po.GroupConfig;
+import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryTask;
+import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryTaskLog;
+import com.aizuda.easy.retry.server.persistence.mybatis.po.SceneConfig;
+import com.aizuda.easy.retry.server.persistence.support.ConfigAccess;
+import com.aizuda.easy.retry.server.persistence.support.RetryTaskAccess;
+import com.aizuda.easy.retry.server.service.convert.RetryTaskConverter;
+import com.aizuda.easy.retry.server.service.convert.RetryTaskLogConverter;
+import com.aizuda.easy.retry.server.support.generator.IdGenerator;
+import com.aizuda.easy.retry.server.support.generator.TaskGenerator;
+import com.aizuda.easy.retry.server.support.strategy.WaitStrategies;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.common.collect.Sets;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @author www.byteblogs.com
+ * @date 2023-07-16 11:52:39
+ * @since 2.1.0
+ */
+@Slf4j
+public abstract class AbstractGenerator implements TaskGenerator {
+
+ @Autowired
+ @Qualifier("configAccessProcessor")
+ private ConfigAccess configAccess;
+ @Autowired
+ private List idGeneratorList;
+ @Autowired
+ private RetryTaskMapper retryTaskMapper;
+ @Autowired
+ private SceneConfigMapper sceneConfigMapper;
+ @Autowired
+ private RetryTaskLogMapper retryTaskLogMapper;
+
+ @Override
+ @Transactional
+ public void taskGenerator(TaskContext taskContext) {
+ LogUtils.info(log, "received report data. {}", JsonUtil.toJsonString(taskContext));
+
+ checkAndInitScene(taskContext);
+
+ List taskInfos = taskContext.getTaskInfos();
+
+ Set idempotentIdSet = taskInfos.stream().map(TaskContext.TaskInfo::getIdempotentId).collect(Collectors.toSet());
+
+ // 获取相关的任务,用户幂等校验
+ List retryTasks = retryTaskMapper.selectList(new LambdaQueryWrapper()
+ .eq(RetryTask::getGroupName, taskContext.getGroupName())
+ .eq(RetryTask::getSceneName, taskContext.getSceneName())
+ .in(RetryTask::getIdempotentId, idempotentIdSet));
+
+ Map> retryTaskMap = retryTasks.stream().collect(Collectors.groupingBy(RetryTask::getIdempotentId));
+
+ List waitInsertTasks = new ArrayList<>();
+ List waitInsertTaskLogs = new ArrayList<>();
+ LocalDateTime now = LocalDateTime.now();
+ for (TaskContext.TaskInfo taskInfo : taskInfos) {
+ Pair, List> pair = doConvertTask(retryTaskMap, taskContext, now, taskInfo);
+ waitInsertTasks.addAll(pair.getKey());
+ waitInsertTaskLogs.addAll(pair.getValue());
+ }
+
+ RequestDataHelper.setPartition(taskContext.getGroupName());
+ Assert.isTrue(waitInsertTasks.size() == retryTaskMapper.batchInsert(waitInsertTasks), () -> new EasyRetryServerException("failed to report data"));
+ Assert.isTrue(waitInsertTaskLogs.size() == retryTaskLogMapper.batchInsert(waitInsertTaskLogs),
+ () -> new EasyRetryServerException("新增重试日志失败"));
+ }
+
+ /**
+ * @param retryTaskMap
+ * @param now
+ * @param taskInfo
+ */
+ private Pair, List> doConvertTask(Map> retryTaskMap,
+ TaskContext taskContext, LocalDateTime now,
+ TaskContext.TaskInfo taskInfo) {
+ List waitInsertTasks = new ArrayList<>();
+ List waitInsertTaskLogs = new ArrayList<>();
+
+ // 判断是否存在与幂等ID相同的任务
+ List list = retryTaskMap.get(taskInfo.getIdempotentId()).stream()
+ .filter(retryTask -> taskContext.getGroupName().equals(retryTask.getGroupName())
+ && taskContext.getSceneName().equals(retryTask.getSceneName())).collect(Collectors.toList());
+ // 说明存在相同的任务
+ if (!CollectionUtils.isEmpty(list)) {
+ LogUtils.warn(log, "interrupted reporting in retrying task. [{}]", JsonUtil.toJsonString(taskInfo));
+ return Pair.of(waitInsertTasks, waitInsertTaskLogs);
+ }
+
+ RetryTask retryTask = RetryTaskConverter.INSTANCE.toRetryTask(taskInfo);
+ retryTask.setUniqueId(getIdGenerator(taskContext.getGroupName()));
+ retryTask.setTaskType(TaskTypeEnum.RETRY.getType());
+ retryTask.setGroupName(taskContext.getGroupName());
+ retryTask.setSceneName(taskContext.getSceneName());
+ retryTask.setCreateDt(now);
+ retryTask.setUpdateDt(now);
+
+ if (StringUtils.isBlank(retryTask.getExtAttrs())) {
+ retryTask.setExtAttrs(StringUtils.EMPTY);
+ }
+
+ retryTask.setNextTriggerAt(WaitStrategies.randomWait(1, TimeUnit.SECONDS, 60, TimeUnit.SECONDS).computeRetryTime(null));
+ waitInsertTasks.add(retryTask);
+
+ // 初始化日志
+ RetryTaskLog retryTaskLog = RetryTaskLogConverter.INSTANCE.toRetryTask(retryTask);
+ retryTaskLog.setTaskType(TaskTypeEnum.RETRY.getType());
+ retryTaskLog.setCreateDt(now);
+ waitInsertTaskLogs.add(retryTaskLog);
+
+ return Pair.of(waitInsertTasks, waitInsertTaskLogs);
+ }
+
+ private void checkAndInitScene( TaskContext taskContext) {
+ SceneConfig sceneConfig = configAccess.getSceneConfigByGroupNameAndSceneName(taskContext.getGroupName(), taskContext.getSceneName());
+ if (Objects.isNull(sceneConfig)) {
+
+ GroupConfig groupConfig = configAccess.getGroupConfigByGroupName(taskContext.getGroupName());
+ if (Objects.isNull(groupConfig)) {
+ throw new EasyRetryServerException("failed to report data, no group configuration found. groupName:[{}]", taskContext.getGroupName());
+ }
+
+ if (groupConfig.getInitScene().equals(StatusEnum.NO.getStatus())) {
+ throw new EasyRetryServerException("failed to report data, no scene configuration found. groupName:[{}] sceneName:[{}]", taskContext.getGroupName(), taskContext.getSceneName());
+ } else {
+ // 若配置了默认初始化场景配置,则发现上报数据的时候未配置场景,默认生成一个场景
+ initScene(taskContext.getGroupName(), taskContext.getSceneName());
+ }
+ }
+
+ }
+
+ /**
+ * 若配置了默认初始化场景配置,则发现上报数据的时候未配置场景,默认生成一个场景
+ * backOff(退避策略): 等级策略
+ * maxRetryCount(最大重试次数): 26
+ * triggerInterval(间隔时间): see: {@link DelayLevelEnum}
+ *
+ * @param groupName 组名称
+ * @param sceneName 场景名称
+ */
+ private void initScene(String groupName, String sceneName) {
+ SceneConfig sceneConfig;
+ sceneConfig = new SceneConfig();
+ sceneConfig.setGroupName(groupName);
+ sceneConfig.setSceneName(sceneName);
+ sceneConfig.setSceneStatus(StatusEnum.YES.getStatus());
+ sceneConfig.setBackOff(WaitStrategies.WaitStrategyEnum.DELAY_LEVEL.getBackOff());
+ sceneConfig.setMaxRetryCount(DelayLevelEnum._21.getLevel());
+ sceneConfig.setDescription("自动初始化场景");
+ Assert.isTrue(1 == sceneConfigMapper.insert(sceneConfig), () -> new EasyRetryServerException("init scene error"));
+ }
+
+ /**
+ * 获取分布式id
+ *
+ * @param groupName 组id
+ * @return 分布式id
+ */
+ private String getIdGenerator(String groupName) {
+
+ GroupConfig groupConfig = configAccess.getGroupConfigByGroupName(groupName);
+ for (final IdGenerator idGenerator : idGeneratorList) {
+ if (idGenerator.supports(groupConfig.getIdGeneratorMode())) {
+ return idGenerator.idGenerator(groupName);
+ }
+ }
+
+ throw new EasyRetryServerException("id generator mode not configured. [{}]", groupName);
+ }
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ClientReportRetryGenerator.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ClientReportRetryGenerator.java
new file mode 100644
index 00000000..63023125
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ClientReportRetryGenerator.java
@@ -0,0 +1,19 @@
+package com.aizuda.easy.retry.server.support.generator.task;
+
+import com.aizuda.easy.retry.server.enums.TaskGeneratorScene;
+import org.springframework.stereotype.Component;
+
+/**
+ * 客户端上报任务生成器
+ *
+ * @author www.byteblogs.com
+ * @date 2023-07-16 11:51:56
+ * @since 2.1.0
+ */
+@Component
+public class ClientReportRetryGenerator extends AbstractGenerator {
+ @Override
+ public boolean supports(int scene) {
+ return TaskGeneratorScene.CLIENT_REPORT.getScene() == scene;
+ }
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaBatchRetryGenerator.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaBatchRetryGenerator.java
new file mode 100644
index 00000000..0dbf8ed0
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaBatchRetryGenerator.java
@@ -0,0 +1,19 @@
+package com.aizuda.easy.retry.server.support.generator.task;
+
+import com.aizuda.easy.retry.server.enums.TaskGeneratorScene;
+import org.springframework.stereotype.Component;
+
+/**
+ * 控制台手动批量新增
+ *
+ * @author www.byteblogs.com
+ * @date 2023-07-16 11:51:56
+ * @since 2.1.0
+ */
+@Component
+public class ManaBatchRetryGenerator extends AbstractGenerator {
+ @Override
+ public boolean supports(int scene) {
+ return TaskGeneratorScene.MANA_BATCH.getScene() == scene;
+ }
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaSingleRetryGenerator.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaSingleRetryGenerator.java
new file mode 100644
index 00000000..83813728
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/ManaSingleRetryGenerator.java
@@ -0,0 +1,19 @@
+package com.aizuda.easy.retry.server.support.generator.task;
+
+import com.aizuda.easy.retry.server.enums.TaskGeneratorScene;
+import org.springframework.stereotype.Component;
+
+/**
+ * 控制台手动单个新增
+ *
+ * @author www.byteblogs.com
+ * @date 2023-07-16 11:51:56
+ * @since 2.1.0
+ */
+@Component
+public class ManaSingleRetryGenerator extends AbstractGenerator {
+ @Override
+ public boolean supports(int scene) {
+ return TaskGeneratorScene.MANA_SINGLE.getScene() == scene;
+ }
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/TaskContext.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/TaskContext.java
new file mode 100644
index 00000000..fa5a027a
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/generator/task/TaskContext.java
@@ -0,0 +1,57 @@
+package com.aizuda.easy.retry.server.support.generator.task;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author www.byteblogs.com
+ * @date 2023-07-16 21:26:52
+ * @since
+ */
+@Data
+public class TaskContext {
+
+ /**
+ * 加密的groupId
+ */
+ private String groupName;
+
+ /**
+ * 加密的sceneId
+ */
+ private String sceneName;
+
+ /**
+ * 任务信息
+ */
+ private List taskInfos;
+
+ @Data
+ public static class TaskInfo {
+ /**
+ * 业务唯一id
+ */
+ private String idempotentId;
+
+ /**
+ * 执行器名称
+ */
+ private String executorName;
+
+ /**
+ * 业务唯一编号
+ */
+ private String bizNo;
+
+ /**
+ * 客户端上报参数
+ */
+ private String argsStr;
+
+ /**
+ * 额外扩展参数
+ */
+ private String extAttrs;
+ }
+}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/controller/RetryTaskController.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/controller/RetryTaskController.java
index e775f2c5..e40dcc8d 100644
--- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/controller/RetryTaskController.java
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/controller/RetryTaskController.java
@@ -4,12 +4,7 @@ import com.aizuda.easy.retry.common.core.model.Result;
import com.aizuda.easy.retry.server.service.RetryTaskService;
import com.aizuda.easy.retry.server.web.annotation.LoginRequired;
import com.aizuda.easy.retry.server.web.model.base.PageResult;
-import com.aizuda.easy.retry.server.web.model.request.BatchDeleteRetryTaskVO;
-import com.aizuda.easy.retry.server.web.model.request.GenerateRetryIdempotentIdVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskQueryVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskUpdateStatusRequestVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskSaveRequestVO;
-import com.aizuda.easy.retry.server.web.model.request.RetryTaskUpdateExecutorNameRequestVO;
+import com.aizuda.easy.retry.server.web.model.request.*;
import com.aizuda.easy.retry.server.web.model.response.RetryTaskResponseVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
@@ -80,4 +75,10 @@ public class RetryTaskController {
public Integer deleteRetryTask(@RequestBody @Validated BatchDeleteRetryTaskVO requestVO) {
return retryTaskService.deleteRetryTask(requestVO);
}
+
+ @LoginRequired
+ @PostMapping("/batch")
+ public Integer parseLogs(@RequestBody @Validated ParseLogsVO parseLogsVO) {
+ return retryTaskService.parseLogs(parseLogsVO);
+ }
}
diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/model/request/ParseLogsVO.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/model/request/ParseLogsVO.java
new file mode 100644
index 00000000..ad64056f
--- /dev/null
+++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/web/model/request/ParseLogsVO.java
@@ -0,0 +1,37 @@
+package com.aizuda.easy.retry.server.web.model.request;
+
+import lombok.Data;
+import org.hibernate.validator.constraints.NotBlank;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 解析参数模型
+ *
+ * @author: www.byteblogs.com
+ * @date: 2023-07-15 23:15
+ */
+@Data
+public class ParseLogsVO {
+
+ /**
+ * 客户端打印的上报日志信息
+ */
+ @NotBlank(message = "日志信息不能为空")
+ private String logStr;
+
+ /**
+ * 组名称
+ */
+ @NotBlank(message = "组名称不能为空")
+ private String groupName;
+
+ /**
+ * 场景名称
+ */
+ @NotBlank(message = "场景名称不能为空")
+ private String sceneName;
+
+ @NotNull(message = "重试状态不能为空")
+ private Integer retryStatus;
+}
diff --git a/easy-retry-server/src/main/resources/mapper/RetryTaskLogMapper.xml b/easy-retry-server/src/main/resources/mapper/RetryTaskLogMapper.xml
index d2388266..288c27f7 100644
--- a/easy-retry-server/src/main/resources/mapper/RetryTaskLogMapper.xml
+++ b/easy-retry-server/src/main/resources/mapper/RetryTaskLogMapper.xml
@@ -86,4 +86,13 @@
+
+
+
+ INSERT INTO retry_task_log (unique_id, group_name, scene_name, idempotent_id, biz_no, executor_name, args_str, ext_attrs, retry_status, task_type, create_dt)
+ VALUES
+
+ (#{item.uniqueId}, #{item.groupName}, #{item.sceneName}, #{item.idempotentId}, #{item.bizNo}, #{item.executorName}, #{item.argsStr}, #{item.extAttrs}, #{item.retryStatus}, #{item.taskType}, #{item.createDt})
+
+
diff --git a/easy-retry-server/src/main/resources/mapper/RetryTaskMapper.xml b/easy-retry-server/src/main/resources/mapper/RetryTaskMapper.xml
index 1e42f7e4..dbebd0a6 100644
--- a/easy-retry-server/src/main/resources/mapper/RetryTaskMapper.xml
+++ b/easy-retry-server/src/main/resources/mapper/RetryTaskMapper.xml
@@ -68,4 +68,12 @@
from retry_task_${partition}
+
+
+ INSERT INTO retry_task_${partition} (unique_id, group_name, scene_name, idempotent_id, biz_no, executor_name, args_str, ext_attrs, next_trigger_at, retry_count, retry_status, task_type, create_dt, update_dt)
+ VALUES
+
+ (#{item.uniqueId}, #{item.groupName}, #{item.sceneName}, #{item.idempotentId}, #{item.bizNo}, #{item.executorName}, #{item.argsStr}, #{item.extAttrs}, #{item.nextTriggerAt}, #{item.retryCount}, #{item.retryStatus}, #{item.taskType}, #{item.createDt}, #{item.updateDt})
+
+
diff --git a/frontend/src/api/manage.js b/frontend/src/api/manage.js
index 0d536f9a..7148fa82 100644
--- a/frontend/src/api/manage.js
+++ b/frontend/src/api/manage.js
@@ -14,6 +14,7 @@ const api = {
retryTaskPage: '/retry-task/list',
retryTaskById: '/retry-task/',
saveRetryTask: '/retry-task',
+ batchSaveRetryTask: '/retry-task/batch',
idempotentIdGenerate: '/retry-task/generate/idempotent-id',
batchUpdate: '/retry-task/batch',
deleteRetryTask: '/retry-task/batch',
@@ -115,6 +116,14 @@ export function saveRetryTask (data) {
})
}
+export function batchSaveRetryTask (data) {
+ return request({
+ url: api.batchSaveRetryTask,
+ method: 'post',
+ data
+ })
+}
+
export function getTotalPartition () {
return request({
url: api.totalPartition,
diff --git a/frontend/src/views/task/RetryTaskList.vue b/frontend/src/views/task/RetryTaskList.vue
index 3b4a5644..6ed9add7 100644
--- a/frontend/src/views/task/RetryTaskList.vue
+++ b/frontend/src/views/task/RetryTaskList.vue
@@ -66,7 +66,8 @@
-
新增
+
单个
+
批量
删除
@@ -115,6 +116,8 @@
+
+
@@ -125,6 +128,7 @@ import { getAllGroupNameList, getRetryTaskPage, getSceneList, updateRetryTaskSta
import { STable } from '@/components'
import SaveRetryTask from './form/SaveRetryTask'
import BatchUpdateRetryTaskInfo from './form/BatchUpdateRetryTaskInfo'
+import BatchSaveRetryTask from '@/views/task/form/BatchSaveRetryTask.vue'
export default {
name: 'RetryTask',
@@ -133,7 +137,8 @@ export default {
ATextarea,
STable,
SaveRetryTask,
- BatchUpdateRetryTaskInfo
+ BatchUpdateRetryTaskInfo,
+ BatchSaveRetryTask
},
data () {
return {
@@ -285,6 +290,9 @@ export default {
handleNew () {
this.$refs.saveRetryTask.isShow(true, null)
},
+ handleBatchNew () {
+ this.$refs.batchSaveRetryTask.isShow(true, null)
+ },
handleChange (value) {
getSceneList({ groupName: value }).then((res) => {
this.sceneList = res.data
diff --git a/frontend/src/views/task/form/BatchSaveRetryTask.vue b/frontend/src/views/task/form/BatchSaveRetryTask.vue
new file mode 100644
index 00000000..5a06118e
--- /dev/null
+++ b/frontend/src/views/task/form/BatchSaveRetryTask.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+ handleChange(value)"
+ >
+ {{ item }}
+
+
+
+
+
+ {{ item.sceneName }}
+
+
+
+
+ {{ value }}
+
+
+
+
+
+ 获取日志信息?
+
+
+
+
+
+
+
+
+
+