如何在使用Quarkus Hibernate Reactive和quarkus-reactive-client时使用一些阻塞方法?

but5z9lq  于 2023-03-30  发布在  React
关注(0)|答案(3)|浏览(160)

我试图调用一个reactive rest,但在这样做的时候,我必须调用它内部的另一个请求,并创建几个文件夹,但quarkus-hibernate-reactive显示下面的错误,什么是最佳实践?

Error:

Caused by: java.lang.IllegalStateException: The current thread cannot be blocked: vert.x-eventloop-thread-2
    at io.smallrye.mutiny.operators.UniBlockingAwait.await(UniBlockingAwait.java:29)

我的代码如下:

@POST
@javax.ws.rs.Path("/add") 
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
@Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN })
public Uni<Response> addUser(@HeaderParam("userName") String addedBy) throws Exception{
     //Here I have one if condition which is checking from database if user exist!

     if (checkUser(addedBy).await().indefinitely().intValue() > 0) {
        //then creatingfolders

        if (createFolders(addedBy) > 0) {
             UserBean u = new UserBean(addedBy);
             return Uni.createFrom().item(userRepository.addUser(u)).onItem().transform(f -> f != null ? Response.ok(f) : Response.ok(null))
                 .onItem().transform(ResponseBuilder::build);
        }
     }
}

public Uni<Long> addUser(UserBean userIN) {
   return Panache.withTransaction(userIN::persist)
                .replaceWith(userIN.getId());
}

我们如何才能让它等待创建文件夹和检查用户存在的完成?我已经尝试使用@Blocking,但它不起作用。请帮助

bksxznpy

bksxznpy1#

您应该切换到常规的Hibernate ORM而不是Hibernate Reactive,或者以React式的方式将操作链接在一起。
而不是执行checkUser(addedBy).await().indefinitely().intValue(),执行以下操作:

checkUser(addedBy).onItem().transformToUni(count -> {
   ....
})
koaltpgm

koaltpgm2#

你提到你已经试过阻塞注解了,但是你用对了吗?我相信有两种,但只有一种有效。

bvuwiixz

bvuwiixz3#

这个问题的答案是runSubscriptionOn-vertx事件循环线程不允许你在上运行阻塞代码,以避免阻塞事件处理。但只有当你使用await()或类似的组合时才会发生这种情况,而不是当其他阻塞或昂贵的操作运行时(如阻塞IO操作),在 * 任何一种 * 情况下,你都应该在不同的worker/pool上运行:

import io.smallrye.mutiny.infrastructure.Infrastructure;

Uni<String> uni = Uni.createFrom()
        .item(this::invokeRemoteServiceUsingBlockingIO)
        .runSubscriptionOn(Infrastructure.getDefaultWorkerPool());
//                                        ''''''''''''''''''''

请注意,您显然需要使用一个延迟项(供应商等),否则您仍然会阻塞事件线程。
另见:https://smallrye.io/smallrye-mutiny/latest/guides/imperative-to-reactive/#running-blocking-code-on-subscription
此外,vertx有一个文件系统模块(你可以在Bean中注入Vertx),它允许你被动地处理文件,所以在这种情况下,你甚至不需要它:

@Inject
io.vertx.mutiny.core.Vertx vertx;
//       ''''''
Uni<Void> uni = vertx.fileSystem().mkdir("/foo");

相关问题