use of io.servicetalk.concurrent.api.CompositeCloseable in project servicetalk by apple.
the class PredicateRouterOffloadingTest method tearDown.
@AfterEach
void tearDown() throws Exception {
if (client != null) {
client.close();
}
final CompositeCloseable closeable = newCompositeCloseable();
if (context != null) {
closeable.append(context);
}
closeable.closeAsync().toFuture().get();
}
use of io.servicetalk.concurrent.api.CompositeCloseable in project servicetalk by apple.
the class GatewayServer method main.
/**
* Starts this server.
*
* @param args Program arguments, none supported yet.
* @throws Exception If the server could not be started.
*/
public static void main(String[] args) throws Exception {
// Create an AutoCloseable representing all resources used in this example.
try (CompositeCloseable resources = newCompositeCloseable()) {
// Shared IoExecutor for the application.
IoExecutor ioExecutor = resources.prepend(createIoExecutor());
// Create clients for the different backends we are going to use in the gateway.
StreamingHttpClient recommendationsClient = newClient(ioExecutor, RECOMMENDATIONS_BACKEND_ADDRESS, resources, "recommendations backend");
HttpClient metadataClient = newClient(ioExecutor, METADATA_BACKEND_ADDRESS, resources, "metadata backend").asClient();
HttpClient userClient = newClient(ioExecutor, USER_BACKEND_ADDRESS, resources, "user backend").asClient();
HttpClient ratingsClient = newClient(ioExecutor, RATINGS_BACKEND_ADDRESS, resources, "ratings backend").asClient();
// Gateway supports different endpoints for blocking, streaming or aggregated implementations.
// We create a router to express these endpoints.
HttpPredicateRouterBuilder routerBuilder = new HttpPredicateRouterBuilder();
final StreamingHttpService gatewayService = routerBuilder.whenPathStartsWith("/recommendations/stream").thenRouteTo(new StreamingGatewayService(recommendationsClient, metadataClient, ratingsClient, userClient)).whenPathStartsWith("/recommendations/aggregated").thenRouteTo(new GatewayService(recommendationsClient.asClient(), metadataClient, ratingsClient, userClient)).whenPathStartsWith("/recommendations/blocking").thenRouteTo(new BlockingGatewayService(recommendationsClient.asBlockingClient(), metadataClient.asBlockingClient(), ratingsClient.asBlockingClient(), userClient.asBlockingClient())).buildStreaming();
// Create configurable starter for HTTP server.
// Starting the server will start listening for incoming client requests.
ServerContext serverContext = HttpServers.forPort(8080).ioExecutor(ioExecutor).appendServiceFilter(new BadResponseHandlingServiceFilter()).listenStreamingAndAwait(gatewayService);
LOGGER.info("Listening on {}", serverContext.listenAddress());
// Blocks and awaits shutdown of the server this ServerContext represents.
serverContext.awaitShutdown();
}
}
use of io.servicetalk.concurrent.api.CompositeCloseable in project servicetalk by apple.
the class NoOffloadsStrategyTest method tearDown.
@AfterEach
void tearDown() throws Exception {
CompositeCloseable closeables = newCompositeCloseable();
if (client != null) {
client.close();
}
if (context != null) {
closeables.append(context);
}
closeables.append(ioExecutor).closeAsync().toFuture().get();
}
use of io.servicetalk.concurrent.api.CompositeCloseable in project servicetalk by apple.
the class DefaultSingleAddressHttpClientBuilder method buildStreaming.
private static <U, R> StreamingHttpClient buildStreaming(final HttpClientBuildContext<U, R> ctx) {
final ReadOnlyHttpClientConfig roConfig = ctx.httpConfig().asReadOnly();
final HttpExecutionContext executionContext = ctx.builder.executionContextBuilder.build();
if (roConfig.h2Config() != null && roConfig.hasProxy()) {
throw new IllegalStateException("Proxying is not yet supported with HTTP/2");
}
// Track resources that potentially need to be closed when an exception is thrown during buildStreaming
final CompositeCloseable closeOnException = newCompositeCloseable();
try {
final Publisher<? extends Collection<? extends ServiceDiscovererEvent<R>>> sdEvents = ctx.serviceDiscoverer(executionContext).discover(ctx.address());
ConnectionFactoryFilter<R, FilterableStreamingHttpConnection> connectionFactoryFilter = ctx.builder.connectionFactoryFilter;
ExecutionStrategy connectionFactoryStrategy = ctx.builder.strategyComputation.buildForConnectionFactory();
final SslContext sslContext = roConfig.tcpConfig().sslContext();
if (roConfig.hasProxy() && sslContext != null) {
assert roConfig.connectAddress() != null;
ConnectionFactoryFilter<R, FilterableStreamingHttpConnection> proxy = new ProxyConnectConnectionFactoryFilter<>(roConfig.connectAddress());
connectionFactoryFilter = proxy.append(connectionFactoryFilter);
connectionFactoryStrategy = connectionFactoryStrategy.merge(proxy.requiredOffloads());
}
final HttpExecutionStrategy executionStrategy = executionContext.executionStrategy();
// closed by the LoadBalancer
final ConnectionFactory<R, LoadBalancedStreamingHttpConnection> connectionFactory;
final StreamingHttpRequestResponseFactory reqRespFactory = defaultReqRespFactory(roConfig, executionContext.bufferAllocator());
if (roConfig.isH2PriorKnowledge()) {
H2ProtocolConfig h2Config = roConfig.h2Config();
assert h2Config != null;
connectionFactory = new H2LBHttpConnectionFactory<>(roConfig, executionContext, ctx.builder.connectionFilterFactory, reqRespFactory, connectionFactoryStrategy, connectionFactoryFilter, ctx.builder.loadBalancerFactory::toLoadBalancedConnection);
} else if (roConfig.tcpConfig().preferredAlpnProtocol() != null) {
H1ProtocolConfig h1Config = roConfig.h1Config();
H2ProtocolConfig h2Config = roConfig.h2Config();
connectionFactory = new AlpnLBHttpConnectionFactory<>(roConfig, executionContext, ctx.builder.connectionFilterFactory, new AlpnReqRespFactoryFunc(executionContext.bufferAllocator(), h1Config == null ? null : h1Config.headersFactory(), h2Config == null ? null : h2Config.headersFactory()), connectionFactoryStrategy, connectionFactoryFilter, ctx.builder.loadBalancerFactory::toLoadBalancedConnection);
} else {
H1ProtocolConfig h1Config = roConfig.h1Config();
assert h1Config != null;
connectionFactory = new PipelinedLBHttpConnectionFactory<>(roConfig, executionContext, ctx.builder.connectionFilterFactory, reqRespFactory, connectionFactoryStrategy, connectionFactoryFilter, ctx.builder.loadBalancerFactory::toLoadBalancedConnection);
}
final LoadBalancer<LoadBalancedStreamingHttpConnection> lb = closeOnException.prepend(ctx.builder.loadBalancerFactory.newLoadBalancer(targetAddress(ctx), sdEvents, connectionFactory));
ContextAwareStreamingHttpClientFilterFactory currClientFilterFactory = ctx.builder.clientFilterFactory;
if (roConfig.hasProxy() && sslContext == null) {
// If we're talking to a proxy over http (not https), rewrite the request-target to absolute-form, as
// specified by the RFC: https://tools.ietf.org/html/rfc7230#section-5.3.2
currClientFilterFactory = appendFilter(currClientFilterFactory, ctx.builder.proxyAbsoluteAddressFilterFactory());
}
if (ctx.builder.addHostHeaderFallbackFilter) {
currClientFilterFactory = appendFilter(currClientFilterFactory, new HostHeaderHttpRequesterFilter(ctx.builder.hostToCharSequenceFunction.apply(ctx.builder.address)));
}
FilterableStreamingHttpClient lbClient = closeOnException.prepend(new LoadBalancedStreamingHttpClient(executionContext, lb, reqRespFactory));
if (ctx.builder.retryingHttpRequesterFilter == null) {
ctx.builder.retryingHttpRequesterFilter = DEFAULT_AUTO_RETRIES;
currClientFilterFactory = appendFilter(currClientFilterFactory, ctx.builder.retryingHttpRequesterFilter);
}
HttpExecutionStrategy computedStrategy = ctx.builder.strategyComputation.buildForClient(executionStrategy);
LOGGER.debug("Client for {} created with base strategy {} → computed strategy {}", targetAddress(ctx), executionStrategy, computedStrategy);
return new FilterableClientToClient(currClientFilterFactory != null ? currClientFilterFactory.create(lbClient, lb.eventStream(), ctx.sdStatus) : lbClient, computedStrategy);
} catch (final Throwable t) {
closeOnException.closeAsync().subscribe();
throw t;
}
}
use of io.servicetalk.concurrent.api.CompositeCloseable in project servicetalk by apple.
the class ExecutionStrategyServer method main.
public static void main(String... args) throws Exception {
int port = 8080;
try (CompositeCloseable closeEverything = AsyncCloseables.newCompositeCloseable()) {
Executor executor = Executors.newCachedThreadExecutor(new DefaultThreadFactory("custom"));
// executor will be closed last, servers are prepended before executor.
closeEverything.append(executor);
// Default server configuration.
// -> route offloaded to global executor
System.out.printf("\n%d : default server\n", port);
ServerContext defaultServer = GrpcServers.forPort(port++).listenAndAwait((GreeterService) (ctx, request) -> getReplySingle(request, "default server"));
closeEverything.prepend(defaultServer);
// No offloads strategy specified on the server, async route does not override its strategy.
// -> no offloading, route executed on IoExecutor
System.out.printf("\n%d : no offloading server, async route\n", port);
ServerContext asyncServer = GrpcServers.forPort(port++).initializeHttp(init -> init.executionStrategy(offloadNever())).listenAndAwait((GreeterService) (ctx, request) -> getReplySingle(request, "no offloading server, async route"));
closeEverything.prepend(asyncServer);
// No offloads strategy specified on the server, blocking route does not override its strategy.
// -> no offloading, route executed on IoExecutor
System.out.printf("\n%d : no offloading server, blocking route\n", port);
ServerContext blockingServer = GrpcServers.forPort(port++).initializeHttp(init -> init.executionStrategy(offloadNever())).listenAndAwait((Greeter.BlockingGreeterService) (ctx, request) -> getReply(request, "no offloading server, blocking route"));
closeEverything.prepend(blockingServer);
// No offloads strategy specified on the server, route overrides it to use the default strategy.
// -> route offloaded to global executor
System.out.printf("\n%d : no offloading server, default offloading for the route\n", port);
ServerContext noOffloadsServerRouteOffloads = GrpcServers.forPort(port++).initializeHttp(init -> init.executionStrategy(offloadNever())).listenAndAwait(new Greeter.ServiceFactory.Builder().sayHello(defaultStrategy(), (ctx, request) -> getReplySingle(request, "no offloading server, default offloading for the route")).build());
closeEverything.prepend(noOffloadsServerRouteOffloads);
// No offloads strategy specified on the server, route overrides it to use a custom strategy.
// -> route offloaded to global executor
System.out.printf("\n%d: no offloading server, custom offloading for the route\n", port);
ServerContext noOffloadsServerRouteOffloadCustom = GrpcServers.forPort(port++).initializeHttp(init -> init.executionStrategy(offloadNever())).listenAndAwait(new Greeter.ServiceFactory.Builder().sayHello(CUSTOM_STRATEGY, (ctx, request) -> getReplySingle(request, "no offloading server, custom offloading for the route")).build());
closeEverything.prepend(noOffloadsServerRouteOffloadCustom);
// Server with a default strategy but a custom executor, route does not override its strategy.
// -> route offloaded to custom executor
System.out.printf("\n%d : server with a default offloading and a custom executor\n", port);
ServerContext customExecutorServer = GrpcServers.forPort(port++).initializeHttp(init -> init.executor(executor)).listenAndAwait((GreeterService) (ctx, request) -> getReplySingle(request, "server with a default offloading and a custom executor"));
closeEverything.prepend(customExecutorServer);
// Server has default configuration, route attempts to use no offloads strategy, which is ignored.
// (Too late, already offloaded at the server level)
// -> route offloaded to global executor
System.out.printf("\n%d : default server, no offloading route\n", port);
ServerContext noOffloadsRoute = GrpcServers.forPort(port++).listenAndAwait(new Greeter.ServiceFactory.Builder().sayHello(offloadNever(), (ctx, request) -> getReplySingle(request, "default server, no offloading route")).build());
closeEverything.prepend(noOffloadsRoute);
// Server has default configuration, route attempts to use no offloads strategy via annotation, which is
// ignored. (Too late, already offloaded at the server level)
// -> route offloaded to global executor
System.out.printf("\n%d : default server, no offloading (annotation) route\n", port);
ServerContext noOffloadsAnnotation = GrpcServers.forPort(port++).listenAndAwait(new NoOffloadsGreeterService());
closeEverything.prepend(noOffloadsAnnotation);
// No offloads strategy specified on the server, route overrides it to also use no offloads strategy,
// which is redundant.
// -> no offloading, route executed on IoExecutor
System.out.printf("\n%d : no offloading server, no offloading route\n", port);
ServerContext noOffloadsServerRoute = GrpcServers.forPort(port++).initializeHttp(init -> init.executionStrategy(offloadNever())).listenAndAwait(new Greeter.ServiceFactory.Builder().sayHello(offloadNever(), (ctx, request) -> getReplySingle(request, "no offloading server, no offloading route")).build());
closeEverything.prepend(noOffloadsServerRoute);
noOffloadsServerRoute.awaitShutdown();
}
}
Aggregations