Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3a92e33
Add experimental gRPC streaming over the event bus
zZHorizonZz Jun 9, 2026
1643f48
Refactor EventBus gRPC transport to use `v1alpha` schema and improve …
zZHorizonZz Jun 18, 2026
36ab7b3
Refactor client and server implementation to support multiplexed stre…
zZHorizonZz Jun 20, 2026
813dc13
Refactor EventBus gRPC client and server to return futures for improv…
zZHorizonZz Jun 22, 2026
f2d8be7
Refactor streaming call handshake to use explicit headers, simplify f…
zZHorizonZz Jun 24, 2026
15877e7
Add `EventBusGrpcServerOptions` to configure gRPC server settings, su…
zZHorizonZz Jun 24, 2026
7751b79
Add support for configurable wire formats in EventBus gRPC client and…
zZHorizonZz Jun 26, 2026
e50f586
Update `README.md` to clarify gRPC event bus transport design and pro…
zZHorizonZz Jun 28, 2026
fd2db78
Refactor gRPC transport to simplify streaming protocol and remove max…
zZHorizonZz Jun 29, 2026
89f59e9
Remove `MethodType` enum and refactor gRPC methods to use explicit cl…
zZHorizonZz Jul 15, 2026
077c1ed
Initialize `pending` and `state` fields in constructor to improve obj…
zZHorizonZz Jul 15, 2026
d33c3bd
Refactor EventBus gRPC streaming implementation to support backpressu…
zZHorizonZz Jul 18, 2026
6882082
Buffer the event bus inbound stream and grant window on consumption
zZHorizonZz Jul 20, 2026
c48d18c
Give the event bus gRPC server and client a close() method
zZHorizonZz Jul 20, 2026
32254ae
Detect an unreachable peer on the event bus and give the stream up
zZHorizonZz Jul 20, 2026
6732b0a
Refactor event bus gRPC streaming to improve write queuing, backpress…
zZHorizonZz Jul 24, 2026
e38f531
Refactor idle timeout mechanism for improved stream lifecycle management
zZHorizonZz Jul 25, 2026
d3f7d08
Add test and implementation for concurrent stream handling with buffe…
zZHorizonZz Jul 25, 2026
b355713
Introduce heartbeat implementation for improved stream lifecycle mana…
zZHorizonZz Jul 26, 2026
2f88ee9
Refactor server streaming to improve frame handling, async write stat…
zZHorizonZz Jul 27, 2026
4cc6ccc
Refactor liveness management for gRPC streams to add per-peer ping su…
zZHorizonZz Jul 28, 2026
470a180
Add tests for liveness options and improve EventBus gRPC stream ping …
zZHorizonZz Jul 29, 2026
398fe74
Revert the GrpcReadStreamBase message buffering
zZHorizonZz Jul 29, 2026
f862899
Address review on the event bus options and MessageWrite
zZHorizonZz Jul 29, 2026
ad7f849
Drop redundant comments in the event bus impls
zZHorizonZz Jul 29, 2026
ee61a47
Document gRPC event bus message flow, liveness mechanics, and handsha…
zZHorizonZz Jul 30, 2026
d05bede
Rename `pingInterval` to `pingTimeout` for improved clarity in gRPC l…
zZHorizonZz Jul 31, 2026
db0e14e
Refactor to replace `Peer` terminology with `RemoteEndpoint` for impr…
zZHorizonZz Aug 4, 2026
8562b52
Refactor EventBus gRPC client and server APIs to simplify constructor…
zZHorizonZz Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
public interface ServiceMethod<I, O> {

static <Req, Resp> ServiceMethod<Resp, Req> client(ServiceName serviceName, String methodName, GrpcMessageEncoder<Req> encoder, GrpcMessageDecoder<Resp> decoder) {
return client(serviceName, methodName, null, null, encoder, decoder);
}

static <Req, Resp> ServiceMethod<Resp, Req> client(ServiceName serviceName, String methodName, Boolean clientStreaming, Boolean serverStreaming, GrpcMessageEncoder<Req> encoder, GrpcMessageDecoder<Resp> decoder) {
return new ServiceMethod<>() {
@Override
public ServiceName serviceName() {
Expand All @@ -29,6 +33,14 @@ public String methodName() {
return methodName;
}
@Override
public Boolean clientStreaming() {
return clientStreaming;
}
@Override
public Boolean serverStreaming() {
return serverStreaming;
}
@Override
public GrpcMessageDecoder<Resp> decoder() {
return decoder;
}
Expand All @@ -40,6 +52,10 @@ public GrpcMessageEncoder<Req> encoder() {
}

static <Req, Resp> ServiceMethod<Req, Resp> server(ServiceName serviceName, String methodName, GrpcMessageEncoder<Resp> encoder, GrpcMessageDecoder<Req> decoder) {
return server(serviceName, methodName, null, null, encoder, decoder);
}

static <Req, Resp> ServiceMethod<Req, Resp> server(ServiceName serviceName, String methodName, Boolean clientStreaming, Boolean serverStreaming, GrpcMessageEncoder<Resp> encoder, GrpcMessageDecoder<Req> decoder) {
return new ServiceMethod<>() {
@Override
public ServiceName serviceName() {
Expand All @@ -50,6 +66,14 @@ public String methodName() {
return methodName;
}
@Override
public Boolean clientStreaming() {
return clientStreaming;
}
@Override
public Boolean serverStreaming() {
return serverStreaming;
}
@Override
public GrpcMessageDecoder<Req> decoder() {
return decoder;
}
Expand All @@ -70,6 +94,27 @@ public GrpcMessageEncoder<Resp> encoder() {
*/
String methodName();

/**
* @return whether the client side sends a stream of requests, {@code null} when this is not known
*/
default Boolean clientStreaming() {
return null;
}

/**
* @return whether the server side sends a stream of responses, {@code null} when this is not known
*/
default Boolean serverStreaming() {
return null;
}

/**
* Computes the fully qualified method name for a gRPC service method.
* The name is constructed by combining the fully qualified service name
* and the method name, separated by a slash ('/').
*
* @return the fully qualified method name in the format "fullyQualifiedServiceName/methodName".
*/
default String fullMethodName() {
return serviceName().fullyQualifiedName() + "/" + methodName();
}
Expand Down
51 changes: 37 additions & 14 deletions vertx-grpc-docs/src/main/java/examples/GrpcEventBusExamples.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import examples.grpc.*;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.streams.ReadStream;
import io.vertx.docgen.Source;
import io.vertx.grpc.common.WireFormat;
import io.vertx.grpc.eventbus.EventBusGrpcClient;
Expand All @@ -13,16 +14,14 @@
public class GrpcEventBusExamples {

public void createServer(Vertx vertx) {
EventBusGrpcServer server = EventBusGrpcServer.server(vertx);
Future<EventBusGrpcServer> server = EventBusGrpcServer.server(vertx);
}

public void createClient(Vertx vertx) {
EventBusGrpcClient client = EventBusGrpcClient.client(vertx);
Future<EventBusGrpcClient> client = EventBusGrpcClient.client(vertx);
}

public void serverWithService(Vertx vertx) {
EventBusGrpcServer server = EventBusGrpcServer.server(vertx);

Service service = GreeterGrpcService.of(new GreeterService() {
@Override
public Future<HelloReply> sayHello(HelloRequest request) {
Expand All @@ -32,24 +31,48 @@ public Future<HelloReply> sayHello(HelloRequest request) {
}
});

server.addService(service);
EventBusGrpcServer.server(vertx).onSuccess(server -> server.addService(service));
}

public void clientWithService(Vertx vertx) {
EventBusGrpcClient client = EventBusGrpcClient.client(vertx);

GreeterClient greeter = GreeterGrpcClient.create(client);
EventBusGrpcClient.client(vertx).onSuccess(client -> {
GreeterClient greeter = GreeterGrpcClient.create(client);

greeter.sayHello(HelloRequest.newBuilder().setName("World").build())
.onSuccess(reply -> System.out.println("Received: " + reply.getMessage()));
greeter.sayHello(HelloRequest.newBuilder().setName("World").build())
.onSuccess(reply -> System.out.println("Received: " + reply.getMessage()));
});
}

public void jsonWireFormat(Vertx vertx) {
EventBusGrpcClient client = EventBusGrpcClient.client(vertx);
EventBusGrpcClient.client(vertx).onSuccess(client -> {
GreeterClient greeter = GreeterGrpcClient.create(client, WireFormat.JSON);

GreeterClient greeter = GreeterGrpcClient.create(client, WireFormat.JSON);
greeter.sayHello(HelloRequest.newBuilder().setName("World").build())
.onSuccess(reply -> System.out.println("Received: " + reply.getMessage()));
});
}

greeter.sayHello(HelloRequest.newBuilder().setName("World").build())
.onSuccess(reply -> System.out.println("Received: " + reply.getMessage()));
public void streamingServer(Vertx vertx) {
Service service = StreamingGrpcService.of(new StreamingService() {
@Override
public Future<ReadStream<Item>> pipe(ReadStream<Item> request) {
return Future.succeededFuture(request);
}
});

EventBusGrpcServer.server(vertx).onSuccess(server -> server.addService(service));
}

public void streamingClient(Vertx vertx) {
EventBusGrpcClient.client(vertx).onSuccess(client -> {
StreamingClient streaming = StreamingGrpcClient.create(client);

streaming.pipe((stream, err) -> {
stream.write(Item.newBuilder().setValue("a").build());
stream.write(Item.newBuilder().setValue("b").build());
stream.end();
}).onSuccess(response -> response
.handler(item -> System.out.println("Received: " + item.getValue())));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,11 @@ public void onError(Throwable t) {
}

public void eventBusExample(Vertx vertx) {
EventBusGrpcClient.client(vertx).onSuccess(client -> {
GrpcIoClientChannel channel = new GrpcIoClientChannel(client);

EventBusGrpcClient client = EventBusGrpcClient.client(vertx);

GrpcIoClientChannel channel = new GrpcIoClientChannel(client);

GreeterGrpc.GreeterStub greeter = GreeterGrpc.newStub(channel);
GreeterGrpc.GreeterStub greeter = GreeterGrpc.newStub(channel);
});
}

public void stubWithDeadline(GrpcIoClientChannel channel, StreamObserver<HelloReply> observer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,9 @@ public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseOb
}

public void eventBusExample(Vertx vertx, GreeterGrpc.GreeterImplBase service) {

EventBusGrpcServer server = EventBusGrpcServer.server(vertx);

GrpcIoServiceBridge bridge = GrpcIoServiceBridge.bridge(service);

server.addService(bridge);
EventBusGrpcServer.server(vertx).onSuccess(server -> server.addService(bridge));
}

public void reflectionExample(Vertx vertx, HttpServerConfig config, ServerSSLOptions sslOptions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface GreeterGrpcClient extends GreeterClient {
ServiceMethod<examples.grpc.HelloReply, examples.grpc.HelloRequest> SayHello = ServiceMethod.client(
ServiceName.create("examples.grpc", "Greeter"),
"SayHello",
false,
false,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.HelloReply.newBuilder()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public static Service of(GreeterService service) {
public static final io.vertx.grpc.transcoding.TranscodingServiceMethod<examples.grpc.HelloRequest, examples.grpc.HelloReply> SayHello = io.vertx.grpc.transcoding.TranscodingServiceMethod.server(
SERVICE_NAME,
"SayHello",
false,
false,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.HelloRequest.newBuilder()),
SayHello_OPTIONS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface StreamingGrpcClient extends StreamingClient {
ServiceMethod<examples.grpc.Item, examples.grpc.Empty> Source = ServiceMethod.client(
ServiceName.create("examples.grpc", "Streaming"),
"Source",
false,
true,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));

Expand All @@ -34,6 +36,8 @@ public interface StreamingGrpcClient extends StreamingClient {
ServiceMethod<examples.grpc.Empty, examples.grpc.Item> Sink = ServiceMethod.client(
ServiceName.create("examples.grpc", "Streaming"),
"Sink",
true,
false,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.Empty.newBuilder()));

Expand All @@ -43,6 +47,8 @@ public interface StreamingGrpcClient extends StreamingClient {
ServiceMethod<examples.grpc.Item, examples.grpc.Item> Pipe = ServiceMethod.client(
ServiceName.create("examples.grpc", "Streaming"),
"Pipe",
true,
true,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ public static Service of(StreamingService service) {
public static final ServiceMethod<examples.grpc.Empty, examples.grpc.Item> Source = ServiceMethod.server(
SERVICE_NAME,
"Source",
false,
true,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.Empty.newBuilder()));

Expand All @@ -80,6 +82,8 @@ public static Service of(StreamingService service) {
public static final ServiceMethod<examples.grpc.Item, examples.grpc.Empty> Sink = ServiceMethod.server(
SERVICE_NAME,
"Sink",
true,
false,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));

Expand All @@ -89,6 +93,8 @@ public static Service of(StreamingService service) {
public static final ServiceMethod<examples.grpc.Item, examples.grpc.Item> Pipe = ServiceMethod.server(
SERVICE_NAME,
"Pipe",
true,
true,
GrpcMessageEncoder.encoder(),
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));

Expand Down
Loading
Loading