
org.lognet.springboot.grpc.GRpcServerRunner Maven / Gradle / Ivy
// Generated by delombok at Mon Jul 31 05:34:41 UTC 2023
package org.lognet.springboot.grpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.ServerInterceptor;
import io.grpc.ServerInterceptors;
import io.grpc.ServerServiceDefinition;
import io.grpc.health.v1.HealthCheckResponse;
import io.grpc.health.v1.HealthGrpc;
import io.grpc.protobuf.services.ProtoReflectionService;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.lognet.springboot.grpc.autoconfigure.GRpcServerProperties;
import org.lognet.springboot.grpc.context.GRpcServerInitializedEvent;
import org.lognet.springboot.grpc.health.ManagedHealthStatusService;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
/** Hosts embedded gRPC server. */
public class GRpcServerRunner implements SmartLifecycle {
@java.lang.SuppressWarnings("all")
private static final org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger(GRpcServerRunner.class);
private final AtomicBoolean isRunning = new AtomicBoolean(false);
private Optional healthStatusManager = Optional.empty();
@Autowired private AbstractApplicationContext applicationContext;
@Autowired private GRpcServerProperties gRpcServerProperties;
@Autowired private GRpcServicesRegistry registry;
private final Consumer> configurator;
private Server server;
private final ServerBuilder> serverBuilder;
private CountDownLatch latch;
public GRpcServerRunner(Consumer> configurator, ServerBuilder> serverBuilder) {
this.configurator = configurator;
this.serverBuilder = serverBuilder;
}
@Override
public void start() {
if (isRunning()) {
return;
}
log.info("Starting gRPC Server ...");
latch = new CountDownLatch(1);
try {
Collection globalInterceptors = registry.getGlobalInterceptors();
// find and register all GRpcService-enabled beans
List serviceNames = new ArrayList<>();
registry
.getBeanNameToServiceBeanMap()
.forEach(
(name, srv) -> {
ServerServiceDefinition serviceDefinition = srv.bindService();
GRpcService gRpcServiceAnn =
applicationContext.findAnnotationOnBean(name, GRpcService.class);
serviceDefinition =
bindInterceptors(serviceDefinition, gRpcServiceAnn, globalInterceptors);
serverBuilder.addService(serviceDefinition);
if (srv instanceof HealthGrpc.HealthImplBase) {
if (!(srv instanceof ManagedHealthStatusService)) {
throw new FatalBeanException(
String.format(
"Please inherit %s from %s rather than directly from %s",
srv.getClass().getName(),
ManagedHealthStatusService.class.getName(),
HealthGrpc.HealthImplBase.class.getName()));
}
if (healthStatusManager.isPresent()) {
throw new FatalBeanException(
String.format(
"Only 1 single %s service instance is allowed",
ManagedHealthStatusService.class.getName()));
} else {
healthStatusManager = Optional.of((ManagedHealthStatusService) srv);
}
} else {
serviceNames.add(serviceDefinition.getServiceDescriptor().getName());
}
log.info("\'{}\' service has been registered.", srv.getClass().getName());
});
healthStatusManager.ifPresent(
h ->
serviceNames.forEach(
serviceName ->
h.setStatus(serviceName, HealthCheckResponse.ServingStatus.SERVING)));
if (gRpcServerProperties.isEnableReflection()) {
serverBuilder.addService(ProtoReflectionService.newInstance());
log.info("\'{}\' service has been registered.", ProtoReflectionService.class.getName());
}
configurator.accept(serverBuilder);
server = serverBuilder.build().start();
isRunning.set(true);
startDaemonAwaitThread();
log.info("gRPC Server started, listening on port {}.", server.getPort());
applicationContext.publishEvent(new GRpcServerInitializedEvent(applicationContext, server));
} catch (Exception e) {
throw new RuntimeException("Failed to start GRPC server", e);
}
}
private ServerServiceDefinition bindInterceptors(
ServerServiceDefinition serviceDefinition,
GRpcService gRpcService,
Collection globalInterceptors) {
Stream extends ServerInterceptor> privateInterceptors =
Stream.of(gRpcService.interceptors())
.map(
interceptorClass -> {
try {
return 0 < applicationContext.getBeanNamesForType(interceptorClass).length
? applicationContext.getBean(interceptorClass)
: interceptorClass.newInstance();
} catch (Exception e) {
throw new BeanCreationException("Failed to create interceptor instance.", e);
}
});
List interceptors =
Stream.concat(
gRpcService.applyGlobalInterceptors()
? globalInterceptors.stream()
: Stream.empty(),
privateInterceptors)
.distinct()
.sorted(serverInterceptorOrderComparator())
.collect(Collectors.toList());
return ServerInterceptors.intercept(serviceDefinition, interceptors);
}
private Comparator
© 2015 - 2025 Weber Informatics LLC | Privacy Policy