支持多种重试配置,如重试时间间隔,最大重试次数, 错误回调,间隔时间倍数等配置
重试对象:
package com.olivia.sdk.utils.model;
import com.olivia.sdk.utils.$;
import com.olivia.sdk.utils.RunUtils;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.Map;
@Setter
@Getter
@Slf4j
@Accessors(chain = true)
public class AsyncRunAndTry implements Runnable {
private String key;
@Setter(AccessLevel.NONE) // 忽略生成该字段的setter
private Map<String, String> contextMap;
private Runnable bizRunnable;
private Runnable errorRunnable;
@Setter(AccessLevel.NONE) // 忽略生成该字段的setter
private int currentExecIndex = 1;
private int maxLoopCount;
private long intervalTimeMill;
private double multipleTime = 1.0;
@Setter(AccessLevel.NONE) // 忽略生成该字段的setter
private Boolean finalExecResult;
public AsyncRunAndTry() {
contextMap = MDC.getCopyOfContextMap();
}
public void setIntervalTimeMill(int intervalTimeMill) {
$.assertTrueCanIgnoreException(intervalTimeMill > 0, "任务间隔不能小于0");
this.intervalTimeMill = intervalTimeMill;
}
@Override
public void run() {
try {
this.currentExecIndex++;
bizRunnable.run();
log.error("key : {} 执行成功", key);
this.finalExecResult = Boolean.TRUE;
} catch (Exception e) {
log.error("key : {} 执行异常 error:{}", key, e.getMessage());
// log.error("key : {} 执行异常 error:{}", key, e.getMessage(), e);
RunUtils.asyncRunAndTry(this);
}
}
}
实现方法:
package com.olivia.sdk.timer;
import com.olivia.sdk.utils.RunUtils;
import com.olivia.sdk.utils.model.AsyncRunAndTry;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
@Slf4j
@Component
public class TimerUtils {
// 静态单例 Timer 对象
public static final Timer TIMER = new Timer();
/**
* 按固定延迟和周期调度任务
*
* @param key 任务的唯一标识
* @param task 要执行的任务
* @param delay 延迟执行的时间(毫秒)
* @param period 任务执行的周期(毫秒)
* @param logLog 是否记录日志
*/
public static void schedule(String key, Runnable task, long delay, long period, boolean logLog) {
TIMER.schedule(createTimerTask(key, task, logLog), delay, period);
}
/**
* 按固定延迟和周期调度任务,默认记录日志
*
* @param key 任务的唯一标识
* @param task 要执行的任务
* @param delay 延迟执行的时间(毫秒)
* @param period 任务执行的周期(毫秒)
*/
public static void schedule(String key, Runnable task, long delay, long period) {
schedule(key, task, delay, period, true);
}
/**
* 按固定延迟调度一次性任务
*
* @param key 任务的唯一标识
* @param task 要执行的任务
* @param delay 延迟执行的时间(毫秒)
* @param logLog 是否记录日志
*/
public static void schedule(String key, Runnable task, long delay, boolean logLog) {
TIMER.schedule(createTimerTask(key, task, logLog), delay);
}
/**
* 按固定延迟调度一次性任务,默认记录日志
*
* @param key 任务的唯一标识
* @param task 要执行的任务
* @param delay 延迟执行的时间(毫秒)
*/
public static void schedule(String key, Runnable task, long delay) {
schedule(key, task, delay, true);
}
/**
* 创建 TimerTask 对象
*
* @param key 任务的唯一标识
* @param task 要执行的任务
* @param logLog 是否记录日志
* @return TimerTask 对象
*/
private static TimerTask createTimerTask(String key, Runnable task, boolean logLog) {
return new TimerTask() {
@Override
public void run() {
try {
task.run();
if (logLog) {
log.info("schedule key :{} exec:success", key);
}
} catch (Exception e) {
if (logLog) {
log.error("schedule key :{} exec:error: {}", key, e.getMessage(), e);
}
}
}
};
}
/**
* 取消所有调度任务并关闭 Timer
*/
public static void cancel() {
TIMER.cancel();
}
@PreDestroy
public static void destroy() {
log.info("TIMER.purge() :{}", TIMER.purge());
}
public static void schedule(AsyncRunAndTry req) {
if (req == null) {
log.info("req is null return");
return;
}
log.info("AsyncRunAndTry key :{} getCurrentExecIndex: {} getMaxLoopCount :{}", req.getKey(), req.getCurrentExecIndex(), req.getMaxLoopCount());
if (req.getMaxLoopCount() < req.getCurrentExecIndex()) {
if (Objects.nonNull(req.getErrorRunnable())) {
RunUtils.asyncRun(req.getKey(), req.getErrorRunnable());
}
return;
}
long nextTime = Math.round(req.getCurrentExecIndex() * req.getIntervalTimeMill() * req.getMultipleTime());
log.info("key {} 下次执行间隔 nextTime {}", req.getKey(), nextTime);
TimerUtils.schedule(req.getKey(), req, nextTime, false);
}
}
255

被折叠的 条评论
为什么被折叠?



