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 retryableExceptions; /** * 不可重试的异常类型(类名列表) */ private java.util.List 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; } }