feat: 0.0.4.2

1、注解新增是否重试完成抛出异常
2、修复重试完成仍然抛出异常

Signed-off-by: byteblogs168 <598092184@qq.com>
This commit is contained in:
byteblogs168 2022-09-30 16:27:50 +08:00
parent 88761f5d56
commit c7aee3538e
6 changed files with 53 additions and 20 deletions

View File

@ -29,7 +29,7 @@ public class TestExistsTransactionalRetryService {
@Autowired @Autowired
private RemoteService remoteService; private RemoteService remoteService;
@Retryable(scene = "testSimpleInsert", bizNo = "#name", localTimes = 3) @Retryable(scene = "testSimpleInsert", bizNo = "#name", localTimes = 3, isThrowException = false)
@Transactional @Transactional
public String testSimpleInsert(String name) { public String testSimpleInsert(String name) {
@ -50,7 +50,7 @@ public class TestExistsTransactionalRetryService {
Result call = remoteService.call(); Result call = remoteService.call();
System.out.println("-------------->"+call.getMessage()); System.out.println("-------------->"+call.getMessage());
if (call.getStatus() == 0) { if (call.getStatus() == 0) {
throw new UnsupportedOperationException("调用远程失败"); throw new UnsupportedOperationException("调用远程失败" + school.getAddress());
} }
return "testSimpleInsert"+school.getAddress(); return "testSimpleInsert"+school.getAddress();

View File

@ -39,7 +39,7 @@ public class ExistsTransactionalRetryServiceTest {
Mockito.when(remoteService.call()) Mockito.when(remoteService.call())
.thenReturn(new Result(0, "1")) .thenReturn(new Result(0, "1"))
.thenReturn(new Result(0, "2")) .thenReturn(new Result(0, "2"))
.thenReturn(new Result(0, "3")) .thenReturn(new Result(1, "3"))
.thenReturn(new Result(0, "4")) .thenReturn(new Result(0, "4"))
.thenReturn(new Result(0, "5")) .thenReturn(new Result(0, "5"))
; ;
@ -47,7 +47,7 @@ public class ExistsTransactionalRetryServiceTest {
String s = testExistsTransactionalRetryService.testSimpleInsert(UUID.randomUUID().toString()); String s = testExistsTransactionalRetryService.testSimpleInsert(UUID.randomUUID().toString());
System.out.println(s); System.out.println(s);
} catch (Exception e) { } catch (Exception e) {
log.error("", e); log.error("重试未成功", e);
} }
Thread.sleep(90000); Thread.sleep(90000);

View File

@ -68,5 +68,16 @@ public @interface Retryable {
*/ */
int localInterval() default 2; int localInterval() default 2;
/**
* 本地重试完成后是否抛出异常
* 如果不抛出异常则调用需要重试方法的方法则感知不到异常信息
*
* 比如: A->B->C->D->E
* D需要重试 若配置D不抛异常,则A->B->C无法感知若有事物则无法回滚
*
* @return true-抛出 false-不抛出
*/
boolean isThrowException() default true;
} }

View File

@ -22,8 +22,9 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature; import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -39,6 +40,7 @@ import java.util.UUID;
@Aspect @Aspect
@Component @Component
@Slf4j @Slf4j
@Order(PriorityOrdered.HIGHEST_PRECEDENCE + 2)
public class RetryAspect { public class RetryAspect {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@ -69,6 +71,7 @@ public class RetryAspect {
Throwable throwable = null; Throwable throwable = null;
Object result = null; Object result = null;
RetryerResultContext retryerResultContext;
try { try {
result = point.proceed(); result = point.proceed();
} catch (Throwable t) { } catch (Throwable t) {
@ -77,10 +80,20 @@ public class RetryAspect {
LogUtils.debug("开始进行重试 aop [{}]", traceId); LogUtils.debug("开始进行重试 aop [{}]", traceId);
// 入口则开始处理重试 // 入口则开始处理重试
doHandlerRetry(point, traceId, retryable, executorClassName, methodEntrance, throwable); retryerResultContext = doHandlerRetry(point, traceId, retryable, executorClassName, methodEntrance, throwable);
} }
LogUtils.debug("aop 结果处理 traceId:[{}] result:[{}] ", traceId, result, throwable); LogUtils.debug("aop 结果处理 traceId:[{}] result:[{}] ", traceId, result, throwable);
// 若是重试完成了, 则判断是否返回重试完成后的数据
if (Objects.nonNull(retryerResultContext)) {
// 重试成功直接返回结果 若注解配置了isThrowException=false 则不抛出异常
if (retryerResultContext.getRetryResultStatusEnum().getStatus().equals(RetryResultStatusEnum.SUCCESS.getStatus())
|| !retryable.isThrowException()) {
return retryerResultContext.getResult();
}
}
if (throwable != null) { if (throwable != null) {
throw throwable; throw throwable;
} else { } else {
@ -89,7 +102,7 @@ public class RetryAspect {
} }
private void doHandlerRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, String methodEntrance, Throwable throwable) { private RetryerResultContext doHandlerRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, String methodEntrance, Throwable throwable) {
if (!RetrySiteSnapshot.isMethodEntrance(methodEntrance) if (!RetrySiteSnapshot.isMethodEntrance(methodEntrance)
|| RetrySiteSnapshot.isRunning() || RetrySiteSnapshot.isRunning()
@ -106,27 +119,30 @@ public class RetryAspect {
RetrySiteSnapshot.isRetryFlow(), RetrySiteSnapshot.isRetryFlow(),
RetrySiteSnapshot.isRetryForStatusCode() RetrySiteSnapshot.isRetryForStatusCode()
); );
return; return null;
} }
if (!TransactionSynchronizationManager.isActualTransactionActive()) { if (!TransactionSynchronizationManager.isActualTransactionActive()) {
// 无事务, 开启重试 // 无事务, 开启重试
openRetry(point, traceId, retryable, executorClassName, throwable); return openRetry(point, traceId, retryable, executorClassName, throwable);
return;
} }
// 存在事物 // final RetryerResultContext[] retryerResultContext = {null};
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override // 存在事物
public void afterCompletion(int status) { // TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
// 有事务开启重试 //
openRetry(point, traceId, retryable, executorClassName, throwable); // @Override
} // public void afterCompletion(int status) {
}); // // 有事务开启重试
// retryerResultContext[0] = openRetry(point, traceId, retryable, executorClassName, throwable);
// }
// });
return null;
} }
private void openRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, Throwable throwable) { private RetryerResultContext openRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, Throwable throwable) {
try { try {
@ -136,6 +152,7 @@ public class RetryAspect {
LogUtils.debug("aop 结果成功 traceId:[{}] result:[{}]", traceId, context.getResult()); LogUtils.debug("aop 结果成功 traceId:[{}] result:[{}]", traceId, context.getResult());
} }
return context;
} catch (Exception e) { } catch (Exception e) {
LogUtils.error("重试组件处理异常,{}", e); LogUtils.error("重试组件处理异常,{}", e);
@ -145,6 +162,8 @@ public class RetryAspect {
} finally { } finally {
RetrySiteSnapshot.removeAll(); RetrySiteSnapshot.removeAll();
} }
return null;
} }
private void sendMessage(Exception e) { private void sendMessage(Exception e) {

View File

@ -76,6 +76,7 @@ public class RetryableScanner implements Scanner, ApplicationContextAware {
int localTimes = retryable.localTimes(); int localTimes = retryable.localTimes();
int localInterval = retryable.localInterval(); int localInterval = retryable.localInterval();
Class<? extends RetryMethod> retryMethod = retryable.retryMethod(); Class<? extends RetryMethod> retryMethod = retryable.retryMethod();
boolean throwException = retryable.isThrowException();
return new RetryerInfo(retryable.scene(), return new RetryerInfo(retryable.scene(),
executorClassName, executorClassName,
@ -88,7 +89,8 @@ public class RetryableScanner implements Scanner, ApplicationContextAware {
localInterval, localInterval,
bizIdGenerate, bizIdGenerate,
bizNo, bizNo,
retryMethod retryMethod,
throwException
); );
} }

View File

@ -28,4 +28,5 @@ public class RetryerInfo {
private final Class<? extends BizIdGenerate> bizIdGenerate; private final Class<? extends BizIdGenerate> bizIdGenerate;
private final String bizNo; private final String bizNo;
private final Class<? extends RetryMethod> retryMethod; private final Class<? extends RetryMethod> retryMethod;
private final boolean isThrowException;
} }