如果在截止日期之前没有生成任何项目,则使用占位符项目完成 Uni,而不取消处理管道

Complete Uni with placeholder item, without cancelling the processing pipeline, if no item has been produced before deadline

我有一个异步操作管道需要很长时间才能完成,我想 如果管道在截止日期之前没有生成项目,让 Uni 继续使用占位符项目,如下所示:

Uni<Item> u = processingPipeline();
return u.ifNoItem().after(Duration.of(10, SECONDS)).recoverWith(placeholderItem);

但是当使用这种方法时,处理管道被取消并且操作链被中断。 是否可以在截止日期到期时用占位符项完成 Uni 而无需取消处理管道?即使错过最后期限,我也希望管道能够进行到最后。 Vert.x 如果有帮助,可用。

谢谢

编辑:

这是我目前尝试过的方法:

Uni<Item> u = processingPipeline();
return Uni.createFrom().emitter(emitter -> {
    vertx.executeBlocking(handler -> {
        u.subscribe().with(emitter::complete);
    }, resultHandler -> {});
    vertx.setTimer(TimeUnit.SECONDS.toMillis(10), timerId -> {
        emitter.complete(placeholderItem);
    });
});

当处理在截止日期之前完成时,这工作正常,但如果截止日期到期并且计时器被触发,它会在发出占位符项目时崩溃并显示 javax.enterprise.context.ContextNotActiveException,并且应用程序似乎也得到了陷入某种僵局。

编辑 2

原来我的大部分问题其实都是由于Hibernate使用不当造成的。在对 Hibernate 事务的管理方式进行一些重构之后,所有随机死锁和其他问题都消失了。

这似乎是对原始问题最优雅的解决方案,即如何在不中断处理的情况下用虚拟项目响应,除非它在截止日期前完成:

Uni<Item> u = processingPipeline();
return Uni.createFrom().emitter(emitter -> {
    u.subscribe().with(emitter::complete);
    vertx.setTimer(TimeUnit.SECONDS.toMillis(10), timerId -> {
        emitter.complete(placeholderItem);
    });
});

管道的取消是预料之中的,因为 ifNoItem().after(duration) 触发了 TimeoutException。所以这个异常被传播为失败,并且这个特定点的上游被取消,这符合反应流语义。

recoverWith是一个故障恢复操作符,订阅这个操作符之后的任何内容。

您可能想看看 recoverWithUni,您可以在其中提供 Uni 作为恢复,而 Uni 将捕获管道的其余部分在此特定超时失败点后重新订阅。

希望对您有所帮助。