Skip to content

Commit

Permalink
feat (core): Introduce EnolaGrpcInProcess
Browse files Browse the repository at this point in the history
  • Loading branch information
vorburger committed Sep 30, 2023
1 parent 9322533 commit fa3fd96
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 20 deletions.
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ maven.install(
"com.google.api.grpc:proto-google-common-protos:2.25.1",
"io.grpc:grpc-netty:1.54.1", # Alternative: grpc-netty-shaded
"io.grpc:grpc-stub:1.54.1",
"io.grpc:grpc-core:1.54.1", # for inprocess
"org.apache.tomcat:annotations-api:6.0.53", # NOT :tomcat-annotations-api
# kubernetes:client-java also depends on Protobuf (+gRPC?), version may need to be upgraded together
"io.kubernetes:client-java:18.0.1",
Expand Down
1 change: 1 addition & 0 deletions core/impl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ java_library(
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
"@maven//:io_grpc_grpc_api",
"@maven//:io_grpc_grpc_core", # for inprocess
"@maven//:io_grpc_grpc_stub",
"@maven//:org_slf4j_slf4j_api",
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2023 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.core.grpc;

import dev.enola.core.EnolaService;
import dev.enola.core.proto.EnolaServiceGrpc;

import io.grpc.ManagedChannel;
import io.grpc.Server;
import io.grpc.inprocess.InProcessChannelBuilder;
import io.grpc.inprocess.InProcessServerBuilder;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class EnolaGrpcInProcess implements AutoCloseable {

private final EnolaService service;
private final Server server;
private final ManagedChannel channel;
private final EnolaServiceGrpc.EnolaServiceBlockingStub client;

public EnolaGrpcInProcess(EnolaService service) throws IOException {
this.service = service;
var uniqueName = InProcessServerBuilder.generateName();
var builder = InProcessServerBuilder.forName(uniqueName).directExecutor(); // as below
builder.addService(new EnolaGrpcService(service)); // as in EnolaGrpcServer
server = builder.build().start();

InProcessChannelBuilder channelBuilder = InProcessChannelBuilder.forName(uniqueName);
channelBuilder.directExecutor(); // as above
channel = channelBuilder.build();

client = EnolaServiceGrpc.newBlockingStub(channel);
}

public EnolaServiceGrpc.EnolaServiceBlockingStub getClient() {
return client;
}

@Override
public void close() throws Exception {
// As in GrpcServerRule#after() and GrpcCleanupRule...
channel.shutdown();
server.shutdown();

try {
channel.awaitTermination(7, TimeUnit.SECONDS);
server.awaitTermination(7, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} finally {
channel.shutdownNow();
server.shutdownNow();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public EnolaGrpcServer(EnolaService service) {

public EnolaGrpcServer start(int port) throws IOException {
var builder = ServerBuilder.forPort(port);
builder.addService(new EnolaGrpcService(service));
builder.addService(new EnolaGrpcService(service)); // as in EnolaGrpcInProcess
server = builder.build().start();
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static java.util.concurrent.TimeUnit.SECONDS;

import dev.enola.common.io.resource.ClasspathResource;
import dev.enola.core.EnolaService;
import dev.enola.core.EnolaServiceProvider;
import dev.enola.core.meta.EntityKindRepository;
import dev.enola.core.proto.EnolaServiceGrpc;
Expand All @@ -35,31 +36,37 @@
import org.junit.Test;

public class EnolaGrpcServerTest {

@Test
public void grpc() throws Exception {
var model = new ClasspathResource("demo-model.yaml");
var ekr = new EntityKindRepository().load(model);
var service = new EnolaServiceProvider().get(ekr);
try (var enolaServer = new EnolaGrpcServer(service).start(0)) {
public void remoting() throws Exception {
try (var enolaServer = new EnolaGrpcServer(service()).start(0)) {
// similarly in dev.enola.demo.ServerTest
var port = enolaServer.getPort();
var endpoint = "localhost:" + port;
var credz = InsecureChannelCredentials.create();
ManagedChannel channel = Grpc.newChannelBuilder(endpoint, credz).build();
var client = EnolaServiceGrpc.newBlockingStub(channel).withDeadlineAfter(3, SECONDS);

var id =
ID.newBuilder()
.setNs("demo")
.setEntity("bar")
.addPaths("a")
.addPaths("b")
.build();
var request = GetEntityRequest.newBuilder().setId(id).build();
var response = client.getEntity(request);
assertThat(response.getEntity().getLinkMap()).hasSize(1);

check(EnolaServiceGrpc.newBlockingStub(channel).withDeadlineAfter(3, SECONDS));
channel.shutdownNow().awaitTermination(3, SECONDS);
}
}

@Test
public void inProcess() throws Exception {
try (var enolaServer = new EnolaGrpcInProcess(service())) {
check(enolaServer.getClient());
}
}

private EnolaService service() throws Exception {
var model = new ClasspathResource("demo-model.yaml");
var ekr = new EntityKindRepository().load(model);
return new EnolaServiceProvider().get(ekr);
}

private void check(EnolaServiceGrpc.EnolaServiceBlockingStub client) {
var id = ID.newBuilder().setNs("demo").setEntity("bar").addPaths("a").addPaths("b").build();
var request = GetEntityRequest.newBuilder().setId(id).build();
var response = client.getEntity(request);
assertThat(response.getEntity().getLinkMap()).hasSize(1);
}
}
2 changes: 2 additions & 0 deletions docs/use/server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ There is also a REST API which returns JSON if you replace `ui` with `api` in th
so e.g. on <http://localhost:8080/api/entity/demo.book/ABC/0-13-140731-7/1>.

The `--grpcPort` flag starts [the Enola gRPC API](.././../dev/proto/core#enolaservice).
It can be called e.g. using a "generic" gRPC Client, such as [ktr0731's Evans](https://github.com/ktr0731/evans)
or [asarkar's OkGRPC](https://github.com/asarkar/okgrpc).
2 changes: 1 addition & 1 deletion maven_install.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
"__INPUT_ARTIFACTS_HASH": -1408292160,
"__INPUT_ARTIFACTS_HASH": 1511132585,
"__RESOLVED_ARTIFACTS_HASH": -1683949065,
"artifacts": {
"aopalliance:aopalliance": {
Expand Down

0 comments on commit fa3fd96

Please sign in to comment.