可重试执行器异常 (RetryableExecutorException)

如果您在执行器执行过程中遭遇了网络连接抖动、下游服务暂时不可用或类似的可重试瞬时错误(即稍后再次调用便有大概率成功恢复的瞬态异常),您可以主动抛出 RetryableExecutorException。 此时,StackSaga 引擎将暂时挂起当前正向推进,并将该事务暴露给下一次分布式调度窗口进行自动重试。 因为引擎通过该异常语义明确知晓:尽管执行器在当前这一毫秒发生了失败,但该错误属于暂时性波动,通过稍后重试完全可以安全自愈。

如果您未在代码中妥善捕获此类网络异常,方法可能会直接向上抛出未经处理的 RuntimeException。 所有未受控的运行时异常将被 StackSaga 引擎默认捕获并视为非可重试异常,进而直接触发逆向回滚。 因此,如果错误属于不可重试的业务硬性失败,您应当显式将其包装为 NonRetryableExecutorException 抛出。

可重试执行器异常 (RetryableExecutorException) 允许在以下执行器的具体方法中抛出:

执行器类型 doProcess() 方法 doRevert() 方法

Query Executor (查询执行器)

✔

✔

Command Executor (指令执行器)

✔

✔

Revert Before Executor (前置回滚执行器)

✔

Revert After Executor (后置回滚执行器)

✔

精准识别异常是否具备可重试性至关重要。 如果在执行业务调用时未对抛出的瞬态异常进行区分捕获,任何一次偶发的网络超时都会导致整个分布式事务过早放弃正向推进并触发不必要的全链路回滚。 因此,强烈建议在 doProcess() 方法内部妥善捕获下游客户端(如 Feign、WebClient)抛出的连接级异常并包装为 RetryableExecutorException。
@SagaExecutor(
        executeFor = "user-service",
        liveCheck = true,
        value = "CheckUserExecutor"
)
@AllArgsConstructor
public class CheckUserExecutor implements QueryExecutor<OrderDomainEntity> {

    private final UserService userService;
    @Override
    public ProcessStepManager<OrderDomainEntity> doProcess(
            ProcessStack processStack,
            OrderDomainEntity domainEntity,
            ProcessStepManagerUtil<OrderDomainEntity> stepManagerUtil
    ) throws RetryableExecutorException, NonRetryableExecutorException {

        try {

            ResponseEntity<UserDetailDto> userDetail = this.userService.getUserDetail(domainEntity.getUsername());
            ...
        } catch (FeignException.ServiceUnavailable unavailableException) {
            // 捕获下游服务暂时不可用(503)异常,包装为可重试异常抛出
            throw RetryableExecutorException.of(unavailableException);
        }
    }

}