package com.mes.task.model;
|
|
import lombok.Builder;
|
import lombok.Data;
|
|
/**
|
* 重试策略配置
|
*
|
* @author mes
|
* @since 2025-01-XX
|
*/
|
@Data
|
@Builder
|
public class RetryPolicy {
|
|
/**
|
* 最大重试次数
|
*/
|
@Builder.Default
|
private int maxRetryCount = 3;
|
|
/**
|
* 初始重试间隔(毫秒)
|
*/
|
@Builder.Default
|
private long initialRetryIntervalMs = 1000;
|
|
/**
|
* 重试间隔增长倍数(指数退避)
|
*/
|
@Builder.Default
|
private double backoffMultiplier = 2.0;
|
|
/**
|
* 最大重试间隔(毫秒)
|
*/
|
@Builder.Default
|
private long maxRetryIntervalMs = 30000;
|
|
/**
|
* 是否启用指数退避
|
*/
|
@Builder.Default
|
private boolean enableExponentialBackoff = true;
|
|
/**
|
* 可重试的异常类型(类名列表)
|
*/
|
private java.util.List<String> retryableExceptions;
|
|
/**
|
* 不可重试的异常类型(类名列表)
|
*/
|
private java.util.List<String> nonRetryableExceptions;
|
|
/**
|
* 默认重试策略
|
*/
|
public static RetryPolicy defaultPolicy() {
|
return RetryPolicy.builder()
|
.maxRetryCount(3)
|
.initialRetryIntervalMs(1000)
|
.backoffMultiplier(2.0)
|
.maxRetryIntervalMs(30000)
|
.enableExponentialBackoff(true)
|
.build();
|
}
|
|
/**
|
* 计算重试间隔
|
*
|
* @param retryAttempt 当前重试次数(从1开始)
|
* @return 重试间隔(毫秒)
|
*/
|
public long calculateRetryInterval(int retryAttempt) {
|
if (!enableExponentialBackoff) {
|
return initialRetryIntervalMs;
|
}
|
|
long interval = (long) (initialRetryIntervalMs * Math.pow(backoffMultiplier, retryAttempt - 1));
|
return Math.min(interval, maxRetryIntervalMs);
|
}
|
|
/**
|
* 判断异常是否可重试
|
*
|
* @param exception 异常对象
|
* @return 是否可重试
|
*/
|
public boolean isRetryable(Throwable exception) {
|
if (exception == null) {
|
return false;
|
}
|
|
String exceptionClassName = exception.getClass().getName();
|
|
// 检查不可重试列表
|
if (nonRetryableExceptions != null) {
|
for (String nonRetryable : nonRetryableExceptions) {
|
if (exceptionClassName.contains(nonRetryable)) {
|
return false;
|
}
|
}
|
}
|
|
// 检查可重试列表
|
if (retryableExceptions != null && !retryableExceptions.isEmpty()) {
|
for (String retryable : retryableExceptions) {
|
if (exceptionClassName.contains(retryable)) {
|
return true;
|
}
|
}
|
return false; // 如果指定了可重试列表,但当前异常不在列表中,则不可重试
|
}
|
|
// 默认策略:网络异常、超时异常可重试,其他不可重试
|
return isDefaultRetryable(exception);
|
}
|
|
/**
|
* 默认重试判断逻辑
|
*/
|
private boolean isDefaultRetryable(Throwable exception) {
|
String exceptionClassName = exception.getClass().getName().toLowerCase();
|
String message = exception.getMessage() != null ? exception.getMessage().toLowerCase() : "";
|
|
// 网络相关异常
|
if (exceptionClassName.contains("timeout") ||
|
exceptionClassName.contains("connection") ||
|
exceptionClassName.contains("network") ||
|
message.contains("timeout") ||
|
message.contains("connection") ||
|
message.contains("网络")) {
|
return true;
|
}
|
|
// 业务异常通常不可重试
|
if (exceptionClassName.contains("illegalargument") ||
|
exceptionClassName.contains("illegalstate") ||
|
exceptionClassName.contains("validation")) {
|
return false;
|
}
|
|
// 其他异常默认不可重试
|
return false;
|
}
|
}
|