Class BlockingOffloadInterceptor

java.lang.Object
org.a2aproject.sdk.server.grpc.quarkus.BlockingOffloadInterceptor
All Implemented Interfaces:
io.grpc.ServerInterceptor

@ApplicationScoped public class BlockingOffloadInterceptor extends Object implements io.grpc.ServerInterceptor
gRPC server interceptor that offloads handler execution from the Vert.x event loop to a worker thread, using a forked gRPC Context.

In Quarkus separate-server mode (quarkus.grpc.server.use-separate-server=true), the @Blocking annotation is ignored and gRPC handlers run on the Vert.x event loop. Synchronous operations like sendMessage() deadlock the event loop. This interceptor wraps the onHalfClose() callback to run the handler on a worker thread instead.

The context is forked (Context.fork()) so that the handler's outbound gRPC calls do not inherit the inbound call's cancellation signal. Without this, Quarkus' ContextStorageOverride propagates the server context through the ManagedExecutor, causing outbound client calls to be cancelled when the inbound caller disconnects.

This applies to both unary and server-streaming methods (which both have a single inbound request). Client-streaming and bidi-streaming methods are excluded.

  • Constructor Details

    • BlockingOffloadInterceptor

      @Inject public BlockingOffloadInterceptor(Executor executor)
  • Method Details

    • interceptCall

      public <ReqT,RespT> io.grpc.ServerCall.Listener<ReqT> interceptCall(io.grpc.ServerCall<ReqT,RespT> call, io.grpc.Metadata headers, io.grpc.ServerCallHandler<ReqT,RespT> next)
      Specified by:
      interceptCall in interface io.grpc.ServerInterceptor