In my router-handler I need to await
for the event-bus request to make it synchronous.
The code looks like so:
router.patch '/api/check' handler this::validateField
void validateField( RoutingContext rc ) {
log.info 'validate start'
CountDownLatch countDownLatch = new CountDownLatch( 1 )
Future<Message> fut = vertx.eventBus().request( 'validate', 'msg' ).onComplete{ countDownLatch.countDown() }
boolean done = countDownLatch.await 4, TimeUnit.SECONDS
if( !done )
rc.json 'service.failure'
else if( fut.failed() ){
ReplyException cause = (ReplyException)fut.cause()
rc.json ReplyFailure.RECIPIENT_FAILURE == cause?.failureType ? cause.message : 'service.failure'
}else
rc.json 'ok'
}
The code above produces the following log output:
[vert.x-eventloop-thread-2] 10:11:03.940 INFO my.Klass - validate start
[vertx-blocked-thread-checker] 10:11:06.297 WARN i.v.core.impl.BlockedThreadChecker - Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 2357 ms, time limit is 2000 ms
[vertx-blocked-thread-checker] 10:11:07.298 WARN i.v.core.impl.BlockedThreadChecker - Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3357 ms, time limit is 2000 ms
As you can see, the countDownLatch
blocks the event-loop-thread for 4 seconds before it's timeout occurs and completes unconditionally.
It doesn't matter if the EB-consumer is reachable and what it responses. The thread simply gets blocked.
The same behavior occurs with java's CompletableFuture
.
Now, if I change the handler
to blockingHandler
in 1st line, the whole thing starts to work just as expected:
router.patch '/api/check' blockingHandler this::validateField
The code reacts properly on NO_HANDLERS
and on valid consumer requests and is waiting as long as needed.
Why does it behave like that?
While the event loop is blocked waiting for the future to complete, it cannot handle the event that completes the future.
In this case, it's one of the worker pool threads which is blocked waiting for the future to complete, and then the future is completed by the event loop thread.