feat&fix: 1.1.0

1. 变更重试流量请求头信息
2. 修复管理界面日期显示问题
3. 停止策略改为责任链模式
This commit is contained in:
www.byteblogs.com 2023-05-02 15:15:09 -12:00
parent 9d2c4e3e83
commit 3275a24632
38 changed files with 2488 additions and 64 deletions

View File

@ -2,7 +2,7 @@ package com.aizuda.easy.retry.client.core.intercepter;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.log.LogUtils;
import com.aizuda.easy.retry.common.core.model.XRetryHeaders;
import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
@ -28,13 +28,13 @@ public class HeaderAspect {
public void before(){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String xRetry = attributes.getRequest().getHeader(SystemConstants.X_RETRY_HEAD_KEY);
String xRetry = attributes.getRequest().getHeader(SystemConstants.EASY_RETRY_HEAD_KEY);
if (Objects.nonNull(xRetry)) {
// 标记进入方法的时间
RetrySiteSnapshot.setEntryMethodTime(System.currentTimeMillis());
LogUtils.info(log, "easy-retry 拦截器 xRetry:[{}]", xRetry);
RetrySiteSnapshot.setRetryHeader(JsonUtil.parseObject(xRetry, XRetryHeaders.class));
RetrySiteSnapshot.setRetryHeader(JsonUtil.parseObject(xRetry, EasyRetryHeaders.class));
}
}
@ -64,7 +64,7 @@ public class HeaderAspect {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletResponse response = attributes.getResponse();
response.addHeader(SystemConstants.X_RETRY_STATUS_CODE_KEY, RetrySiteSnapshot.getRetryStatusCode());
response.addHeader(SystemConstants.EASY_RETRY_STATUS_CODE_KEY, RetrySiteSnapshot.getRetryStatusCode());
// 服务端重试的在com.x.retry.client.core.client.RetryEndPoint 中进行清除threadLocal
if (Objects.nonNull(RetrySiteSnapshot.getStage()) && RetrySiteSnapshot.EnumStage.REMOTE.getStage() == RetrySiteSnapshot.getStage()) {

View File

@ -1,7 +1,7 @@
package com.aizuda.easy.retry.client.core.intercepter;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.model.XRetryHeaders;
import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders;
import lombok.Getter;
import java.util.Objects;
@ -32,7 +32,7 @@ public class RetrySiteSnapshot {
/**
* 重试请求头
*/
private static final ThreadLocal<XRetryHeaders> RETRY_HEADER = new ThreadLocal<>();
private static final ThreadLocal<EasyRetryHeaders> RETRY_HEADER = new ThreadLocal<>();
/**
* 状态码
@ -76,11 +76,11 @@ public class RetrySiteSnapshot {
return EnumStatus.RUNNING.status == getStatus();
}
public static XRetryHeaders getRetryHeader() {
public static EasyRetryHeaders getRetryHeader() {
return RETRY_HEADER.get();
}
public static void setRetryHeader(XRetryHeaders headers) {
public static void setRetryHeader(EasyRetryHeaders headers) {
RETRY_HEADER.set(headers);
}
@ -88,9 +88,9 @@ public class RetrySiteSnapshot {
* 是否是重试流量
*/
public static boolean isRetryFlow() {
XRetryHeaders retryHeader = getRetryHeader();
EasyRetryHeaders retryHeader = getRetryHeader();
if (Objects.nonNull(retryHeader)) {
return retryHeader.isXRetry();
return retryHeader.isEasyRetry();
}
return false;
@ -105,7 +105,7 @@ public class RetrySiteSnapshot {
}
public static boolean isRetryForStatusCode() {
return Objects.nonNull(getRetryStatusCode()) && getRetryStatusCode().equals(SystemConstants.X_RETRY_STATUS_CODE);
return Objects.nonNull(getRetryStatusCode()) && getRetryStatusCode().equals(SystemConstants.EASY_RETRY_STATUS_CODE);
}
public static Long getEntryMethodTime() {

View File

@ -4,7 +4,7 @@ import com.aizuda.easy.retry.client.core.exception.EasyRetryClientException;
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.log.LogUtils;
import com.aizuda.easy.retry.common.core.model.XRetryHeaders;
import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
@ -30,7 +30,7 @@ public class RequestHeaderPlugins {
public static Map<String, String> requestHeader() {
Map<String, String> header = new HashMap<>();
XRetryHeaders retryHeader = RetrySiteSnapshot.getRetryHeader();
EasyRetryHeaders retryHeader = RetrySiteSnapshot.getRetryHeader();
// 传递请求头
if (Objects.nonNull(retryHeader)) {
@ -44,7 +44,7 @@ public class RequestHeaderPlugins {
throw new EasyRetryClientException("调用链超时, 不在继续调用后面请求");
}
header.put(SystemConstants.X_RETRY_HEAD_KEY, JsonUtil.toJsonString(retryHeader));
header.put(SystemConstants.EASY_RETRY_HEAD_KEY, JsonUtil.toJsonString(retryHeader));
}
return header;

View File

@ -23,8 +23,8 @@ public class ResponseHeaderPlugins {
public static void responseHeader(Map<String, List<String>> header) {
// 获取不重试标志
if (header.containsKey(SystemConstants.X_RETRY_STATUS_CODE_KEY)) {
List<String> statusCode = header.get(SystemConstants.X_RETRY_STATUS_CODE_KEY);
if (header.containsKey(SystemConstants.EASY_RETRY_STATUS_CODE_KEY)) {
List<String> statusCode = header.get(SystemConstants.EASY_RETRY_STATUS_CODE_KEY);
RetrySiteSnapshot.setRetryStatusCode(statusCode.get(0));
}
}

View File

@ -9,17 +9,17 @@ public class SystemConstants {
/**
* 请求头 key
*/
public static final String X_RETRY_HEAD_KEY = "easy-retry";
public static final String EASY_RETRY_HEAD_KEY = "easy-retry";
/**
* 异常重试码 key
*/
public static final String X_RETRY_STATUS_CODE_KEY = "easy-retry-status";
public static final String EASY_RETRY_STATUS_CODE_KEY = "easy-retry-status";
/**
* 异常重试码
*/
public static final String X_RETRY_STATUS_CODE = "519";
public static final String EASY_RETRY_STATUS_CODE = "519";

View File

@ -9,17 +9,17 @@ import lombok.Data;
* @date : 2022-04-16 22:20
*/
@Data
public class XRetryHeaders {
public class EasyRetryHeaders {
/**
* 是否是重试流量
*/
private boolean xRetry;
private boolean easyRetry;
/**
* 重试下发的ID
*/
private String xRetryId;
private String easyRetryId;
/**
* 调用链超时时间 单位毫秒(ms)

View File

@ -14,10 +14,12 @@ import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
/**
* @author: byteblogs
@ -107,6 +109,8 @@ public class JsonUtil {
* 内部类处理Json
*/
public static class JsonMapper {
private static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String YYYY_MM_DD = "yyyy-MM-dd";
private static ObjectMapper objectMapper = jacksonObjectMapper();
@ -114,6 +118,8 @@ public class JsonUtil {
// 初始化全局Jackson 序列化工具
ObjectMapper objectMapper = new ObjectMapper();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
DateTimeFormatter localDateFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
// 忽略未知属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@ -129,27 +135,27 @@ public class JsonUtil {
javaTimeModule.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(String.valueOf(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()));
jsonGenerator.writeString(localDate.format(localDateFormatter));
}
});
javaTimeModule.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(String.valueOf(localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
jsonGenerator.writeString(localDateTime.format(dateTimeFormatter));
}
});
javaTimeModule.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String value = jsonParser.getValueAsString();
return StringUtils.isBlank(value) ? null : new Timestamp(Long.valueOf(value.trim())).toLocalDateTime().toLocalDate();
return StringUtils.isBlank(value) ? null : LocalDateTime.parse(value, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)).toLocalDate();
}
});
javaTimeModule.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String value = jsonParser.getValueAsString();
return StringUtils.isBlank(value) ? null : new Timestamp(Long.valueOf(value.trim())).toLocalDateTime();
return StringUtils.isBlank(value) ? null : LocalDateTime.parse(value, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
}
});

View File

@ -26,6 +26,7 @@ public class RetryTaskLogServiceImpl implements RetryTaskLogService {
private RetryTaskLogMapper retryTaskLogMapper;
private RetryTaskLogResponseVOConverter retryTaskLogResponseVOConverter = new RetryTaskLogResponseVOConverter();
@Override
public PageResult<List<RetryTaskLogResponseVO>> getRetryTaskLogPage(RetryTaskLogQueryVO queryVO) {
@ -46,7 +47,7 @@ public class RetryTaskLogServiceImpl implements RetryTaskLogService {
}
retryTaskLogLambdaQueryWrapper.select(RetryTaskLog::getGroupName, RetryTaskLog::getId, RetryTaskLog::getSceneName,
RetryTaskLog::getBizId, RetryTaskLog::getBizNo, RetryTaskLog::getErrorMessage, RetryTaskLog::getRetryStatus);
RetryTaskLog::getBizId, RetryTaskLog::getBizNo, RetryTaskLog::getErrorMessage, RetryTaskLog::getRetryStatus, RetryTaskLog::getCreateDt);
PageDTO<RetryTaskLog> retryTaskLogPageDTO = retryTaskLogMapper.selectPage(pageDTO, retryTaskLogLambdaQueryWrapper.orderByDesc(RetryTaskLog::getCreateDt));
return new PageResult<>(

View File

@ -22,6 +22,20 @@ public interface RetryContext<V> {
*/
void setCallResult(V v);
/**
* 调用客户端发生异常信息
*
* @param e 异常
*/
void setException(Exception e);
/**
* 是否发生异常
*
* @return
*/
boolean hasException();
/**
* 等待策略
*

View File

@ -15,4 +15,21 @@ public interface StopStrategy {
* @return
*/
boolean shouldStop(RetryContext retryContext);
/**
* 是否触发此停止策略
*
* @param retryContext {@link RetryContext} 重试上下文
* @return
*/
boolean supports(RetryContext retryContext);
/**
* 按照正序排列重试过滤器
* 若相同则按照加入的顺序
*
* @return 排序的值
*/
int order();
}

View File

@ -5,7 +5,9 @@ import com.aizuda.easy.retry.server.persistence.mybatis.po.ServerNode;
import com.aizuda.easy.retry.server.support.RetryContext;
import com.aizuda.easy.retry.server.support.WaitStrategy;
import lombok.Data;
import lombok.Getter;
import java.util.Objects;
import java.util.Set;
/**
@ -15,6 +17,7 @@ import java.util.Set;
* @date : 2021-11-29 18:32
*/
@Data
@Getter
public class MaxAttemptsPersistenceRetryContext<V> implements RetryContext<V> {
/**
@ -22,6 +25,11 @@ public class MaxAttemptsPersistenceRetryContext<V> implements RetryContext<V> {
*/
private V callResult;
/**
* 异常信息
*/
private Exception exception;
/**
* 等待策略
*/
@ -46,4 +54,14 @@ public class MaxAttemptsPersistenceRetryContext<V> implements RetryContext<V> {
public void setCallResult(V v) {
this.callResult = v;
}
@Override
public void setException(Exception e) {
this.exception = e;
}
@Override
public boolean hasException() {
return Objects.nonNull(exception);
}
}

View File

@ -6,7 +6,7 @@ import com.aizuda.easy.retry.client.model.RetryCallbackDTO;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.log.LogUtils;
import com.aizuda.easy.retry.common.core.model.Result;
import com.aizuda.easy.retry.common.core.model.XRetryHeaders;
import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryTask;
import com.aizuda.easy.retry.server.persistence.mybatis.po.ServerNode;
@ -62,10 +62,10 @@ public class CallbackRetryResultActor extends AbstractActor {
// 设置header
HttpHeaders requestHeaders = new HttpHeaders();
XRetryHeaders xRetryHeaders = new XRetryHeaders();
xRetryHeaders.setXRetry(Boolean.TRUE);
xRetryHeaders.setXRetryId(IdUtil.simpleUUID());
requestHeaders.add(SystemConstants.X_RETRY_HEAD_KEY, JsonUtil.toJsonString(xRetryHeaders));
EasyRetryHeaders easyRetryHeaders = new EasyRetryHeaders();
easyRetryHeaders.setEasyRetry(Boolean.TRUE);
easyRetryHeaders.setEasyRetryId(IdUtil.simpleUUID());
requestHeaders.add(SystemConstants.EASY_RETRY_HEAD_KEY, JsonUtil.toJsonString(easyRetryHeaders));
HttpEntity<RetryCallbackDTO> requestEntity = new HttpEntity<>(retryCallbackDTO, requestHeaders);

View File

@ -8,7 +8,7 @@ import com.aizuda.easy.retry.client.model.DispatchRetryResultDTO;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.log.LogUtils;
import com.aizuda.easy.retry.common.core.model.Result;
import com.aizuda.easy.retry.common.core.model.XRetryHeaders;
import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
import com.aizuda.easy.retry.server.exception.EasyRetryServerException;
import com.aizuda.easy.retry.server.persistence.mybatis.mapper.RetryTaskLogMapper;
@ -72,7 +72,10 @@ public class ExecUnitActor extends AbstractActor {
try {
if (Objects.nonNull(serverNode)) {
Object call = retryExecutor.call((Callable<Result<DispatchRetryResultDTO>>) () -> callClient(retryTask, retryTaskLog, serverNode));
retryExecutor.call((Callable<Result<DispatchRetryResultDTO>>) () -> callClient(retryTask, retryTaskLog, serverNode));
if (context.hasException()) {
retryTaskLog.setErrorMessage(context.getException().getMessage());
}
} else {
retryTaskLog.setErrorMessage("暂无可用的客户端POD");
}
@ -113,10 +116,10 @@ public class ExecUnitActor extends AbstractActor {
// 设置header
HttpHeaders requestHeaders = new HttpHeaders();
XRetryHeaders xRetryHeaders = new XRetryHeaders();
xRetryHeaders.setXRetry(Boolean.TRUE);
xRetryHeaders.setXRetryId(IdUtil.simpleUUID());
requestHeaders.add(SystemConstants.X_RETRY_HEAD_KEY, JsonUtil.toJsonString(xRetryHeaders));
EasyRetryHeaders easyRetryHeaders = new EasyRetryHeaders();
easyRetryHeaders.setEasyRetry(Boolean.TRUE);
easyRetryHeaders.setEasyRetryId(IdUtil.simpleUUID());
requestHeaders.add(SystemConstants.EASY_RETRY_HEAD_KEY, JsonUtil.toJsonString(easyRetryHeaders));
HttpEntity<DispatchRetryDTO> requestEntity = new HttpEntity<>(dispatchRetryDTO, requestHeaders);

View File

@ -107,6 +107,7 @@ public class ScanGroupActor extends AbstractActor {
retryContext.setServerNode(clientNodeAllocateHandler.getServerNode(retryTask.getGroupName()));
RetryExecutor<Result<DispatchRetryResultDTO>> executor = RetryBuilder.<Result<DispatchRetryResultDTO>>newBuilder()
.withStopStrategy(StopStrategies.stopException())
.withStopStrategy(StopStrategies.stopResultStatus())
.withWaitStrategy(getWaitWaitStrategy(groupName, retryTask.getSceneName()))
.withFilterStrategy(FilterStrategies.delayLevelFilter())

View File

@ -17,7 +17,7 @@ import java.util.*;
*/
public class RetryBuilder<V> {
private StopStrategy stopStrategy;
private List<StopStrategy> stopStrategies;
private WaitStrategy waitStrategy;
private List<FilterStrategy> filterStrategies;
private RetryContext<V> retryContext;
@ -41,7 +41,11 @@ public class RetryBuilder<V> {
}
public RetryBuilder<V> withStopStrategy(StopStrategy stopStrategy) {
this.stopStrategy = stopStrategy;
if (CollectionUtils.isEmpty(stopStrategies)) {
stopStrategies = new ArrayList<>();
}
stopStrategies.add(stopStrategy);
return this;
}
@ -56,14 +60,16 @@ public class RetryBuilder<V> {
throw new EasyRetryServerException("waitStrategy 不能为null");
}
if (Objects.isNull(stopStrategy)) {
throw new EasyRetryServerException("stopStrategy 不能为null");
}
if (Objects.isNull(retryContext)) {
throw new EasyRetryServerException("retryContext 不能为null");
}
if (CollectionUtils.isEmpty(stopStrategies)) {
stopStrategies = Collections.EMPTY_LIST;
} else {
stopStrategies.sort(Comparator.comparingInt(StopStrategy::order));
}
if (CollectionUtils.isEmpty(filterStrategies)) {
filterStrategies = Collections.EMPTY_LIST;
} else {
@ -72,7 +78,7 @@ public class RetryBuilder<V> {
retryContext.setWaitStrategy(waitStrategy);
return new RetryExecutor<V>(stopStrategy, waitStrategy, filterStrategies, retryContext);
return new RetryExecutor<V>(stopStrategies, waitStrategy, filterStrategies, retryContext);
}
}

View File

@ -9,6 +9,7 @@ import com.aizuda.easy.retry.server.support.WaitStrategy;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
/**
@ -20,16 +21,16 @@ import java.util.concurrent.Callable;
@Slf4j
public class RetryExecutor<V> {
private final StopStrategy stopStrategy;
private final List<StopStrategy> stopStrategies;
private final WaitStrategy waitStrategy;
private final List<FilterStrategy> filterStrategies;
private final RetryContext<V> retryContext;
public RetryExecutor(StopStrategy stopStrategy,
public RetryExecutor(List<StopStrategy> stopStrategies,
WaitStrategy waitStrategy,
List<FilterStrategy> filterStrategies,
RetryContext<V> retryContext) {
this.stopStrategy = stopStrategy;
this.stopStrategies = stopStrategies;
this.waitStrategy = waitStrategy;
this.filterStrategies = filterStrategies;
this.retryContext = retryContext;
@ -59,17 +60,29 @@ public class RetryExecutor<V> {
V call = null;
try {
call = callable.call();
retryContext.setCallResult(call);
} catch (Exception e) {
log.error("客户端执行失败: [{}]", retryContext.getRetryTask());
retryContext.setException(e);
}
retryContext.setCallResult(call);
// 计算下次触发时间
retryContext.getRetryTask().setNextTriggerAt(waitStrategy.computeRetryTime(retryContext));
boolean isStop = Boolean.TRUE;
// 触发停止策略判断
for (StopStrategy stopStrategy : stopStrategies) {
if (stopStrategy.supports(retryContext)) {
// 必须责任链中的所有停止策略都判断为停止此时才判定为重试完成
if (!stopStrategy.shouldStop(retryContext)) {
isStop = Boolean.FALSE;
}
}
}
ActorRef actorRef;
if (stopStrategy.shouldStop(retryContext)) {
if (isStop) {
// 状态变为完成 FinishActor
actorRef = ActorGenerator.finishActor();
} else {
@ -78,6 +91,7 @@ public class RetryExecutor<V> {
}
actorRef.tell(retryContext.getRetryTask(), actorRef);
return call;
}

View File

@ -22,7 +22,16 @@ public class StopStrategies {
}
/**
* 根据重试结果终止
* 调用客户端发生异常触发停止策略
*
* @return {@link ExceptionStopStrategy} 调用客户端发生异常触发停止策略
*/
public static StopStrategy stopException() {
return new ExceptionStopStrategy();
}
/**
* 根据客户端返回结果判断是否终止重试
*
* @return {@link ResultStatusStopStrategy} 重试结果停止策略
*/
@ -31,7 +40,28 @@ public class StopStrategies {
}
/**
* 根据重试结果集判断是否应该停止
* 调用客户端发生异常触发停止策略
*/
private static final class ExceptionStopStrategy implements StopStrategy {
@Override
public boolean shouldStop(RetryContext retryContext) {
return !retryContext.hasException();
}
@Override
public boolean supports(RetryContext retryContext) {
return true;
}
@Override
public int order() {
return 1;
}
}
/**
* 根据客户端返回结果集判断是否应该停止
*
* 1{@link Result#getStatus()} 不为1 则继续重试
* 2根据{@link Result#getData()}中的statusCode判断是否停止
@ -59,6 +89,16 @@ public class StopStrategies {
Integer status = RetryResultStatusEnum.getRetryResultStatusEnum(statusCode).getStatus();
return RetryResultStatusEnum.SUCCESS.getStatus().equals(status) || RetryResultStatusEnum.STOP.getStatus().equals(status);
}
@Override
public boolean supports(RetryContext retryContext) {
return retryContext instanceof MaxAttemptsPersistenceRetryContext;
}
@Override
public int order() {
return 2;
}
}
}

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/logo.png"><title>Easy-Retry</title><style>.first-loading-wrp{display:flex;justify-content:center;align-items:center;flex-direction:column;min-height:420px;height:100%}.first-loading-wrp>h1{font-size:128px}.first-loading-wrp .loading-wrp{padding:98px;display:flex;justify-content:center;align-items:center}.dot{animation:antRotate 1.2s infinite linear;transform:rotate(45deg);position:relative;display:inline-block;font-size:32px;width:32px;height:32px;box-sizing:border-box}.dot i{width:14px;height:14px;position:absolute;display:block;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.dot i:nth-child(1){top:0;left:0}.dot i:nth-child(2){top:0;right:0;-webkit-animation-delay:.4s;animation-delay:.4s}.dot i:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.8s}.dot i:nth-child(4){bottom:0;left:0;-webkit-animation-delay:1.2s;animation-delay:1.2s}@keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@-webkit-keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@keyframes antSpinMove{to{opacity:1}}@-webkit-keyframes antSpinMove{to{opacity:1}}</style><link href="/css/chunk-39be5683.cd4961ff.css" rel="prefetch"><link href="/css/chunk-4a2f6b49.a04e8eb5.css" rel="prefetch"><link href="/css/chunk-77aaac2a.99cbbcce.css" rel="prefetch"><link href="/css/user.6ccd4506.css" rel="prefetch"><link href="/js/chunk-08798c7e.984d2f3a.js" rel="prefetch"><link href="/js/chunk-1bf36f2c.ab7c2647.js" rel="prefetch"><link href="/js/chunk-244a93b4.d6cff8a4.js" rel="prefetch"><link href="/js/chunk-2515aa86.c58c1b7a.js" rel="prefetch"><link href="/js/chunk-2672acfa.bc252574.js" rel="prefetch"><link href="/js/chunk-2d21a08f.667d7e9a.js" rel="prefetch"><link href="/js/chunk-35f6c8ac.bf2fbc64.js" rel="prefetch"><link href="/js/chunk-39be5683.17f16b23.js" rel="prefetch"><link href="/js/chunk-4a2f6b49.745ee7e8.js" rel="prefetch"><link href="/js/chunk-71608044.5af14532.js" rel="prefetch"><link href="/js/chunk-77aaac2a.a8c64402.js" rel="prefetch"><link href="/js/chunk-bf3addda.365f48f3.js" rel="prefetch"><link href="/js/fail.40283b49.js" rel="prefetch"><link href="/js/lang-zh-CN-account-settings.f8f25eaf.js" rel="prefetch"><link href="/js/lang-zh-CN-account.f7a734c3.js" rel="prefetch"><link href="/js/lang-zh-CN-dashboard-analysis.d7cabd65.js" rel="prefetch"><link href="/js/lang-zh-CN-dashboard.ffd6ecbd.js" rel="prefetch"><link href="/js/lang-zh-CN-form-basicForm.ff3088ac.js" rel="prefetch"><link href="/js/lang-zh-CN-form.39cd9999.js" rel="prefetch"><link href="/js/lang-zh-CN-global.bf0df5c8.js" rel="prefetch"><link href="/js/lang-zh-CN-menu.25425a62.js" rel="prefetch"><link href="/js/lang-zh-CN-result-fail.232762aa.js" rel="prefetch"><link href="/js/lang-zh-CN-result-success.3519c60c.js" rel="prefetch"><link href="/js/lang-zh-CN-result.b3df3bc6.js" rel="prefetch"><link href="/js/lang-zh-CN-setting.8c2ce690.js" rel="prefetch"><link href="/js/lang-zh-CN-user.81513cba.js" rel="prefetch"><link href="/js/lang-zh-CN.6ae67127.js" rel="prefetch"><link href="/js/user.a4cdfea5.js" rel="prefetch"><link href="/css/app.c8c81dfd.css" rel="preload" as="style"><link href="/css/chunk-vendors.f716a607.css" rel="preload" as="style"><link href="/js/app.58d24c5a.js" rel="preload" as="script"><link href="/js/chunk-vendors.b8c3b6d4.js" rel="preload" as="script"><link href="/css/chunk-vendors.f716a607.css" rel="stylesheet"><link href="/css/app.c8c81dfd.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"><div class="first-loading-wrp"><h2>Easy-Retry</h2><div class="loading-wrp"><span class="dot dot-spin"><i></i><i></i><i></i><i></i></span></div><div style="display: flex; justify-content: center; align-items: center;">分布式重试服务平台</div></div></div><script src="//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script><script src="//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js"></script><script src="//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js"></script><script src="//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script><script src="/js/chunk-vendors.b8c3b6d4.js"></script><script src="/js/app.58d24c5a.js"></script></body></html>
<!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/logo.png"><title>Easy-Retry</title><style>.first-loading-wrp{display:flex;justify-content:center;align-items:center;flex-direction:column;min-height:420px;height:100%}.first-loading-wrp>h1{font-size:128px}.first-loading-wrp .loading-wrp{padding:98px;display:flex;justify-content:center;align-items:center}.dot{animation:antRotate 1.2s infinite linear;transform:rotate(45deg);position:relative;display:inline-block;font-size:32px;width:32px;height:32px;box-sizing:border-box}.dot i{width:14px;height:14px;position:absolute;display:block;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.dot i:nth-child(1){top:0;left:0}.dot i:nth-child(2){top:0;right:0;-webkit-animation-delay:.4s;animation-delay:.4s}.dot i:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.8s}.dot i:nth-child(4){bottom:0;left:0;-webkit-animation-delay:1.2s;animation-delay:1.2s}@keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@-webkit-keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@keyframes antSpinMove{to{opacity:1}}@-webkit-keyframes antSpinMove{to{opacity:1}}</style><link href="/css/chunk-39be5683.cd4961ff.css" rel="prefetch"><link href="/css/chunk-4a2f6b49.a04e8eb5.css" rel="prefetch"><link href="/css/chunk-77aaac2a.99cbbcce.css" rel="prefetch"><link href="/css/user.6ccd4506.css" rel="prefetch"><link href="/js/chunk-08798c7e.bfbd5a35.js" rel="prefetch"><link href="/js/chunk-1bf36f2c.b33b2536.js" rel="prefetch"><link href="/js/chunk-244a93b4.89d86add.js" rel="prefetch"><link href="/js/chunk-2515aa86.c6f32c4c.js" rel="prefetch"><link href="/js/chunk-2672acfa.a6a69a7f.js" rel="prefetch"><link href="/js/chunk-2d21a08f.10f9edd8.js" rel="prefetch"><link href="/js/chunk-35f6c8ac.4166a8c0.js" rel="prefetch"><link href="/js/chunk-39be5683.8052daba.js" rel="prefetch"><link href="/js/chunk-4a2f6b49.8726a153.js" rel="prefetch"><link href="/js/chunk-71608044.e21176f4.js" rel="prefetch"><link href="/js/chunk-77aaac2a.a8f6aa61.js" rel="prefetch"><link href="/js/chunk-bf3addda.fece787c.js" rel="prefetch"><link href="/js/fail.f78b643f.js" rel="prefetch"><link href="/js/lang-zh-CN-account-settings.f8f25eaf.js" rel="prefetch"><link href="/js/lang-zh-CN-account.f7a734c3.js" rel="prefetch"><link href="/js/lang-zh-CN-dashboard-analysis.d7cabd65.js" rel="prefetch"><link href="/js/lang-zh-CN-dashboard.ffd6ecbd.js" rel="prefetch"><link href="/js/lang-zh-CN-form-basicForm.ff3088ac.js" rel="prefetch"><link href="/js/lang-zh-CN-form.39cd9999.js" rel="prefetch"><link href="/js/lang-zh-CN-global.bf0df5c8.js" rel="prefetch"><link href="/js/lang-zh-CN-menu.25425a62.js" rel="prefetch"><link href="/js/lang-zh-CN-result-fail.232762aa.js" rel="prefetch"><link href="/js/lang-zh-CN-result-success.3519c60c.js" rel="prefetch"><link href="/js/lang-zh-CN-result.b3df3bc6.js" rel="prefetch"><link href="/js/lang-zh-CN-setting.8c2ce690.js" rel="prefetch"><link href="/js/lang-zh-CN-user.81513cba.js" rel="prefetch"><link href="/js/lang-zh-CN.6ae67127.js" rel="prefetch"><link href="/js/user.d6fd464c.js" rel="prefetch"><link href="/css/app.c8c81dfd.css" rel="preload" as="style"><link href="/css/chunk-vendors.f716a607.css" rel="preload" as="style"><link href="/js/app.a2b44034.js" rel="preload" as="script"><link href="/js/chunk-vendors.b8c3b6d4.js" rel="preload" as="script"><link href="/css/chunk-vendors.f716a607.css" rel="stylesheet"><link href="/css/app.c8c81dfd.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"><div class="first-loading-wrp"><h2>Easy-Retry</h2><div class="loading-wrp"><span class="dot dot-spin"><i></i><i></i><i></i><i></i></span></div><div style="display: flex; justify-content: center; align-items: center;">分布式重试服务平台</div></div></div><script src="//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script><script src="//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js"></script><script src="//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js"></script><script src="//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script><script src="/js/chunk-vendors.b8c3b6d4.js"></script><script src="/js/app.a2b44034.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2308
example/log/sys.log Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,11 +25,11 @@ public class SchoolController {
@GetMapping("/id")
public Result getSchool(HttpServletRequest request, HttpServletResponse response) {
String header = request.getHeader(SystemConstants.X_RETRY_HEAD_KEY);
String header = request.getHeader(SystemConstants.EASY_RETRY_HEAD_KEY);
System.out.println(header);
if (RetrySiteSnapshot.isRetryFlow()) {
response.addHeader(SystemConstants.X_RETRY_STATUS_CODE_KEY, SystemConstants.X_RETRY_STATUS_CODE);
response.addHeader(SystemConstants.EASY_RETRY_STATUS_CODE_KEY, SystemConstants.EASY_RETRY_STATUS_CODE);
}
if (true) {

View File

@ -35,7 +35,6 @@ export default {
},
viewCharts (viewRecords, type = 'day') {
var ds = new DataSet()
console.log(viewRecords)
if (viewRecords === undefined || viewRecords === null) {
return
}

View File

@ -110,7 +110,6 @@ import AInput from 'ant-design-vue/es/input/Input'
import Edit from '@/views/list/table/Edit'
import { getAllGroupNameList, getRetryTaskPage, getSceneList, updateRetryTaskStatus, batchDelete } from '@/api/manage'
import { STable } from '@/components'
import moment from 'moment'
import SaveRetryTask from './form/SaveRetryTask'
import BatchUpdateRetryTaskInfo from './form/BatchUpdateRetryTaskInfo'
@ -167,8 +166,7 @@ export default {
{
title: '下次触发时间',
dataIndex: 'nextTriggerAt',
needTotal: false,
customRender: (text) => moment(text).format('YYYY-MM-DD HH:mm:ss')
needTotal: false
},
{
title: '重试次数',
@ -183,8 +181,7 @@ export default {
{
title: '更新时间',
dataIndex: 'updateDt',
sorter: true,
customRender: (text) => moment(text).format('YYYY-MM-DD HH:mm:ss')
sorter: true
},
{
title: '操作',