Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis Cache doesn't run in worker thread #42253

Closed
zche-theScore opened this issue Jul 31, 2024 · 4 comments · Fixed by #42540
Closed

Redis Cache doesn't run in worker thread #42253

zche-theScore opened this issue Jul 31, 2024 · 4 comments · Fixed by #42540
Labels
Milestone

Comments

@zche-theScore
Copy link

Describe the bug

When I tried to use Redis Cache @CacheResult() in a GraphQL resolver which runs in a worker thread, it hangs and gives and error

Thread Thread[vert.x-worker-thread-3,5,main] has been blocked for 60427 ms, time limit is 60000 ms: io.vertx.core.VertxException: Thread blocked

There's no problem if I switch the GraphQL resolver to using Uni which makes it run in a event-loop thread.
There's no problem if I used Caffeine Cache.
There's no problem if there exists the cache entry in Redis.

Reproducer: https://github.com/zche-theScore/quarkus-redis-cache-blocking

Expected behavior

I didn't see any note saying Redis Cache can only be used on event-loop thread in the docs.

Actual behavior

Redis Cache @CacheResult() makes a worker thread hang.

How to Reproduce?

Reproducer: https://github.com/zche-theScore/quarkus-redis-cache-blocking

Output of uname -a or ver

Darwin ca-on-a-zche.local 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 arm64

Output of java -version

openjdk 22.0.1 2024-04-16 OpenJDK Runtime Environment (build 22.0.1+8-16) OpenJDK 64-Bit Server VM (build 22.0.1+8-16, mixed mode, sharing)

Quarkus version or git rev

3.13.0

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.8 (36645f6c9b5079805ea5009217e36f2cffd34256)

Additional information

No response

@zche-theScore zche-theScore added the kind/bug Something isn't working label Jul 31, 2024
@quarkus-bot
Copy link

quarkus-bot bot commented Jul 31, 2024

/cc @Ladicek (redis), @cescoffier (redis), @gwenneg (cache), @machi1990 (redis)

@Ladicek
Copy link
Contributor

Ladicek commented Aug 9, 2024

I've been looking at this today and while I didn't conclude yet, I found one interesting thing: there's only one Vert.x worker thread in the pool. That thread waits for loading the value, which should also happen on the worker thread pool.

I tried setting quarkus.thread-pool.core-threads=8, but that creates 8 different threads that are not used as Vert.x worker threads, so maybe there's an issue there. Not yet sure what.

@Ladicek
Copy link
Contributor

Ladicek commented Aug 12, 2024

OK, so when I run the app in the prod mode, where the Vert.x worker thread pool and the Quarkus thread pool indeed are identical, it still doesn't work.

Then, I tried replacing the GraphQL resolver with a JAX-RS resource and it works just fine. That suggests that SmallRye GraphQL's execution model is perhaps somewhat different than RESTEasy Reactive's.

I looked further and found that the problem might be in that the Redis cache implementation uses an ordered worker submission. That is, it requests that both actions are executed on the same worker thread. Not sure why that works fine with JAX-RS and doesn't work with GraphQL...

@Ladicek
Copy link
Contributor

Ladicek commented Aug 12, 2024

OK, so I have figured out a workaround -- configure

quarkus.smallrye-graphql.nonblocking.enabled=false

Why does that make it work? The method is clearly blocking, so what's the difference?

The difference is that with quarkus.smallrye-graphql.nonblocking.enabled=false, the GraphQL route is registered as blocking, which essentially boils down to BlockingHandlerDecorator, which is created with the ordered parameter set to false. On the other hand, in the default configuration, the GraphQL route is registered as non-blocking and the blocking is done in BlockingHelper.runBlocking, which doesn't pass the ordered parameter, which is equivalent to passing true.

It seems to me that this should pass false explicitly -- then it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants