Skip to content

Commit ad3f1ff

Browse files
committed
Add experimental gRPC streaming over the event bus
Signed-off-by: Daniel Fiala <danfiala23@gmail.com>
1 parent 8abda78 commit ad3f1ff

27 files changed

Lines changed: 1876 additions & 333 deletions
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.vertx.grpc.common;
2+
3+
/**
4+
* The cardinality of a gRPC service method.
5+
*/
6+
public enum MethodType {
7+
8+
/**
9+
* A single request and a single response.
10+
*/
11+
UNARY,
12+
13+
/**
14+
* A stream of requests and a single response.
15+
*/
16+
CLIENT_STREAMING,
17+
18+
/**
19+
* A single request and a stream of responses.
20+
*/
21+
SERVER_STREAMING,
22+
23+
/**
24+
* A stream of requests and a stream of responses.
25+
*/
26+
BIDI;
27+
28+
/**
29+
* @return whether the client sends a stream of requests
30+
*/
31+
public boolean clientStreaming() {
32+
return this == CLIENT_STREAMING || this == BIDI;
33+
}
34+
35+
/**
36+
* @return whether the server sends a stream of responses
37+
*/
38+
public boolean serverStreaming() {
39+
return this == SERVER_STREAMING || this == BIDI;
40+
}
41+
42+
/**
43+
* @return whether either side streams, i.e. anything other than {@link #UNARY}
44+
*/
45+
public boolean streaming() {
46+
return this != UNARY;
47+
}
48+
}

vertx-grpc-common/src/main/java/io/vertx/grpc/common/ServiceMethod.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
public interface ServiceMethod<I, O> {
2020

2121
static <Req, Resp> ServiceMethod<Resp, Req> client(ServiceName serviceName, String methodName, GrpcMessageEncoder<Req> encoder, GrpcMessageDecoder<Resp> decoder) {
22+
return client(serviceName, methodName, MethodType.UNARY, encoder, decoder);
23+
}
24+
25+
static <Req, Resp> ServiceMethod<Resp, Req> client(ServiceName serviceName, String methodName, MethodType type, GrpcMessageEncoder<Req> encoder, GrpcMessageDecoder<Resp> decoder) {
2226
return new ServiceMethod<>() {
2327
@Override
2428
public ServiceName serviceName() {
@@ -29,6 +33,10 @@ public String methodName() {
2933
return methodName;
3034
}
3135
@Override
36+
public MethodType type() {
37+
return type;
38+
}
39+
@Override
3240
public GrpcMessageDecoder<Resp> decoder() {
3341
return decoder;
3442
}
@@ -40,6 +48,10 @@ public GrpcMessageEncoder<Req> encoder() {
4048
}
4149

4250
static <Req, Resp> ServiceMethod<Req, Resp> server(ServiceName serviceName, String methodName, GrpcMessageEncoder<Resp> encoder, GrpcMessageDecoder<Req> decoder) {
51+
return server(serviceName, methodName, MethodType.UNARY, encoder, decoder);
52+
}
53+
54+
static <Req, Resp> ServiceMethod<Req, Resp> server(ServiceName serviceName, String methodName, MethodType type, GrpcMessageEncoder<Resp> encoder, GrpcMessageDecoder<Req> decoder) {
4355
return new ServiceMethod<>() {
4456
@Override
4557
public ServiceName serviceName() {
@@ -50,6 +62,10 @@ public String methodName() {
5062
return methodName;
5163
}
5264
@Override
65+
public MethodType type() {
66+
return type;
67+
}
68+
@Override
5369
public GrpcMessageDecoder<Req> decoder() {
5470
return decoder;
5571
}
@@ -70,6 +86,24 @@ public GrpcMessageEncoder<Resp> encoder() {
7086
*/
7187
String methodName();
7288

89+
/**
90+
* Retrieves the cardinality of the gRPC service method.
91+
* By default, it will return {@code MethodType.UNARY}, indicating
92+
* a single request and a single response.
93+
*
94+
* @return the {@code MethodType} of the service method
95+
*/
96+
default MethodType type() {
97+
return MethodType.UNARY;
98+
}
99+
100+
/**
101+
* Computes the fully qualified method name for a gRPC service method.
102+
* The name is constructed by combining the fully qualified service name
103+
* and the method name, separated by a slash ('/').
104+
*
105+
* @return the fully qualified method name in the format "fullyQualifiedServiceName/methodName".
106+
*/
73107
default String fullMethodName() {
74108
return serviceName().fullyQualifiedName() + "/" + methodName();
75109
}

vertx-grpc-docs/src/main/java/examples/GrpcEventBusExamples.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import examples.grpc.*;
44
import io.vertx.core.Future;
55
import io.vertx.core.Vertx;
6+
import io.vertx.core.streams.ReadStream;
67
import io.vertx.docgen.Source;
78
import io.vertx.grpc.common.WireFormat;
89
import io.vertx.grpc.eventbus.EventBusGrpcClient;
@@ -52,4 +53,30 @@ public void jsonWireFormat(Vertx vertx) {
5253
greeter.sayHello(HelloRequest.newBuilder().setName("World").build())
5354
.onSuccess(reply -> System.out.println("Received: " + reply.getMessage()));
5455
}
56+
57+
public void streamingServer(Vertx vertx) {
58+
EventBusGrpcServer server = EventBusGrpcServer.server(vertx);
59+
60+
Service service = StreamingGrpcService.of(new StreamingService() {
61+
@Override
62+
public Future<ReadStream<Item>> pipe(ReadStream<Item> request) {
63+
return Future.succeededFuture(request);
64+
}
65+
});
66+
67+
server.addService(service);
68+
}
69+
70+
public void streamingClient(Vertx vertx) {
71+
EventBusGrpcClient client = EventBusGrpcClient.client(vertx);
72+
73+
StreamingClient streaming = StreamingGrpcClient.create(client);
74+
75+
streaming.pipe((stream, err) -> {
76+
stream.write(Item.newBuilder().setValue("a").build());
77+
stream.write(Item.newBuilder().setValue("b").build());
78+
stream.end();
79+
}).onSuccess(response -> response
80+
.handler(item -> System.out.println("Received: " + item.getValue())));
81+
}
5582
}

vertx-grpc-docs/src/main/java/examples/grpc/GreeterGrpcClient.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public interface GreeterGrpcClient extends GreeterClient {
2525
ServiceMethod<examples.grpc.HelloReply, examples.grpc.HelloRequest> SayHello = ServiceMethod.client(
2626
ServiceName.create("examples.grpc", "Greeter"),
2727
"SayHello",
28+
io.vertx.grpc.common.MethodType.UNARY,
2829
GrpcMessageEncoder.encoder(),
2930
GrpcMessageDecoder.decoder(examples.grpc.HelloReply.newBuilder()));
3031

vertx-grpc-docs/src/main/java/examples/grpc/StreamingGrpcClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public interface StreamingGrpcClient extends StreamingClient {
2525
ServiceMethod<examples.grpc.Item, examples.grpc.Empty> Source = ServiceMethod.client(
2626
ServiceName.create("examples.grpc", "Streaming"),
2727
"Source",
28+
io.vertx.grpc.common.MethodType.SERVER_STREAMING,
2829
GrpcMessageEncoder.encoder(),
2930
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));
3031

@@ -34,6 +35,7 @@ public interface StreamingGrpcClient extends StreamingClient {
3435
ServiceMethod<examples.grpc.Empty, examples.grpc.Item> Sink = ServiceMethod.client(
3536
ServiceName.create("examples.grpc", "Streaming"),
3637
"Sink",
38+
io.vertx.grpc.common.MethodType.CLIENT_STREAMING,
3739
GrpcMessageEncoder.encoder(),
3840
GrpcMessageDecoder.decoder(examples.grpc.Empty.newBuilder()));
3941

@@ -43,6 +45,7 @@ public interface StreamingGrpcClient extends StreamingClient {
4345
ServiceMethod<examples.grpc.Item, examples.grpc.Item> Pipe = ServiceMethod.client(
4446
ServiceName.create("examples.grpc", "Streaming"),
4547
"Pipe",
48+
io.vertx.grpc.common.MethodType.BIDI,
4649
GrpcMessageEncoder.encoder(),
4750
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));
4851

vertx-grpc-docs/src/main/java/examples/grpc/StreamingGrpcService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public static Service of(StreamingService service) {
7171
public static final ServiceMethod<examples.grpc.Empty, examples.grpc.Item> Source = ServiceMethod.server(
7272
SERVICE_NAME,
7373
"Source",
74+
io.vertx.grpc.common.MethodType.SERVER_STREAMING,
7475
GrpcMessageEncoder.encoder(),
7576
GrpcMessageDecoder.decoder(examples.grpc.Empty.newBuilder()));
7677

@@ -80,6 +81,7 @@ public static Service of(StreamingService service) {
8081
public static final ServiceMethod<examples.grpc.Item, examples.grpc.Empty> Sink = ServiceMethod.server(
8182
SERVICE_NAME,
8283
"Sink",
84+
io.vertx.grpc.common.MethodType.CLIENT_STREAMING,
8385
GrpcMessageEncoder.encoder(),
8486
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));
8587

@@ -89,6 +91,7 @@ public static Service of(StreamingService service) {
8991
public static final ServiceMethod<examples.grpc.Item, examples.grpc.Item> Pipe = ServiceMethod.server(
9092
SERVICE_NAME,
9193
"Pipe",
94+
io.vertx.grpc.common.MethodType.BIDI,
9295
GrpcMessageEncoder.encoder(),
9396
GrpcMessageDecoder.decoder(examples.grpc.Item.newBuilder()));
9497

0 commit comments

Comments
 (0)