Class GrpcFutures
StreamObserver-to-CompletableFuture adapter for unary
gRPC calls. Drop-in replacement for the Mutiny stub pattern that was
silently eating transport-level failures and hanging the test orchestrator.
Why this exists: Mutiny gRPC stubs (the MutinyXxxGrpc::newMutinyStub
factories) wrap a ClientCall in a Uni. The Mutiny
adapter has a known failure mode where transport-level terminal events from
the underlying ClientCall.Listener don't always materialize into the
Uni's onFailure path — especially when the HTTP/2 state
machine fires events in an order the adapter doesn't expect. The Uni
stays subscribed forever, no callback lands, no thread parks, and the whole
test orchestrator stalls with no log line.
Plain async stubs do not have this problem. A StreamObserver
receives the gRPC framework's terminal events directly: onNext for
the response, onError for any transport or status failure,
onCompleted when the call closes. Nothing in between to lose
events. The channel's HTTP/2 keepalive (keepAliveTime +
keepAliveTimeout on the channel builder) detects dead transports
and fires onError with UNAVAILABLE.
Usage:
{@literal @}GrpcClient("my-service") MyServiceGrpc.MyServiceStub stub;
...
CompletableFuture<MyResponse> future = GrpcFutures.unary(
observer -> stub.myRpc(request, observer));
MyResponse response = future.get(); // blocks the calling (virtual) thread
This is the same shape the kafka-sidecar uses for its outbound RPCs and matches the gRPC documentation's recommended async-stub usage. No application-level deadlines layered on; channel keepalive handles transport-failure detection. Use deadlines only when you have a real application-level "must complete in N seconds" requirement.
-
Method Summary
Modifier and TypeMethodDescriptionstatic <T> CompletableFuture<T> Invokes a unary gRPC call and returns aCompletableFuturethat completes with the single response, fails with the gRPC status, or fails withIllegalStateExceptionif the call closes without producing a response.
-
Method Details
-
unary
Invokes a unary gRPC call and returns aCompletableFuturethat completes with the single response, fails with the gRPC status, or fails withIllegalStateExceptionif the call closes without producing a response.- Type Parameters:
T- the gRPC response message type produced by the call- Parameters:
call- function that takes a responseStreamObserverand initiates the gRPC call (e.g.observer -> stub.rpc(req, observer))- Returns:
- a future completing with the single response, failing with the
gRPC status on transport/status error, or failing with
IllegalStateExceptionif the call closes without a response
-