Java 项目反应器异步发送电子邮件,错误时重试

Java 项目反应器异步发送电子邮件,错误时重试,java,project-reactor,Java,Project Reactor,我需要在用户注册后发送一些数据。我想在主线程中进行第一次尝试,但如果有任何错误,我想每隔10分钟重试5次 @Override public void sendRegisterInfo(MailData data) { Mono.just(data) .doOnNext(this::send) .doOnError(ex -> logger.warn("Main queue {}", ex.getMessage())) .doOnSuc

我需要在用户注册后发送一些数据。我想在主线程中进行第一次尝试,但如果有任何错误,我想每隔10分钟重试5次

@Override
public void sendRegisterInfo(MailData data) {
    Mono.just(data)
        .doOnNext(this::send)
        .doOnError(ex -> logger.warn("Main queue {}", ex.getMessage()))
        .doOnSuccess(d -> logger.info("Send mail to {}", d.getRecipient()))
        .onErrorResume(ex -> retryQueue(data))
        .subscribe();
}

private Mono<MailData> retryQueue(MailData data) {
    return Mono.just(data)
               .delayElement(Duration.of(10, ChronoUnit.MINUTES))
               .doOnNext(this::send)
               .doOnError(ex -> logger.warn("Retry queue {}", ex.getMessage()))
               .doOnSuccess(d -> logger.info("Send mail to {}", d.getRecipient()))
               .retry(5)
               .subscribe();
}
@覆盖
public void sendRegisterInfo(邮件数据){
Mono.just(数据)
.doOnNext(此::发送)
.doError(ex->logger.warn(“主队列{}”,ex.getMessage()))
.doOnSuccess(d->logger.info(“将邮件发送到{}”,d.getRecipient()))
.OneErrorResume(ex->retryQueue(数据))
.subscribe();
}
专用Mono retryQueue(邮件数据){
返回Mono.just(数据)
.delayElement(持续时间(10分钟))
.doOnNext(此::发送)
.doError(ex->logger.warn(“重试队列{}”,例如.getMessage()))
.doOnSuccess(d->logger.info(“将邮件发送到{}”,d.getRecipient()))
.重试(5)
.subscribe();
}
它起作用了。 但我有一些问题:

  • 我是否更正了在
    doOnNext
    函数中进行操作
  • 使用
    delayElement
    在执行之间进行延迟是否正确
  • 等待延迟时线程阻塞了吗
  • 对错误进行重试并在错误之间进行延迟的最佳实践是什么
  • doOnXXX
    用于日志记录是可以的。但对于实际的元素处理,您必须更喜欢使用
    flatMap
    而不是
    doOnNext
    (假设您的处理是异步的/可以转换为返回
    通量
    /
    Mono

  • 这是正确的。另一种方法是将代码转过来,从一个
    Flux.interval
    开始,但是这里的
    delayElement
    更好

  • 延迟在单独的线程/调度程序上运行(默认情况下,
    Schedulers.parallel()
    ),因此不会阻塞主线程

  • 实际上,在
    reactor extra
    插件中有一个
    Retry
    生成器专门用于这种用例:


  • 为什么在doOn**运算符上执行异步处理不合适?我以前听过这句话,但没有明确的理由说明为什么这不是一个好的做法。你基本上打破了反应链,你不会得到成功完成过程或错误的通知。主序列可以提前完成,给您的印象是一切都很顺利,只是异步进程在一秒钟后的某个角落悄悄地失败了。这只适用于纯“开火并忘记”场景,但通常您希望至少重新连接到完整/错误信号