use of io.servicetalk.concurrent.api.Executor 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();
}
}
use of io.servicetalk.concurrent.api.Executor in project servicetalk by apple.
the class InsufficientlySizedExecutorHttpTest method initWhenServerUnderProvisioned.
private void initWhenServerUnderProvisioned(final int capacity, boolean addConnectionAcceptor) throws Exception {
executor = getExecutorForCapacity(capacity);
final HttpExecutionStrategy strategy = offloadAllStrategy();
HttpServerBuilder serverBuilder = forAddress(localAddress(0));
if (addConnectionAcceptor) {
serverBuilder.appendConnectionAcceptorFilter(identity());
}
server = serverBuilder.executor(executor).executionStrategy(strategy).listenStreamingAndAwait((ctx, request, respFactory) -> succeeded(respFactory.ok()));
client = forSingleAddress(serverHostAndPort(server)).buildStreaming();
}
use of io.servicetalk.concurrent.api.Executor in project servicetalk by apple.
the class AbstractCompletableOffloadingTest method testOffloading.
protected int testOffloading(BiFunction<Completable, Executor, Completable> offloadingFunction, TerminalOperation terminal) throws InterruptedException {
Runnable appCode = () -> {
try {
// Insert a custom value into AsyncContext map
AsyncContext.put(ASYNC_CONTEXT_CUSTOM_KEY, ASYNC_CONTEXT_VALUE);
capture(CaptureSlot.APP);
// Add thread/context recording test points
final Completable original = testCompletable.liftSync(subscriber -> {
capture(CaptureSlot.OFFLOADED_SUBSCRIBE);
return subscriber;
}).beforeOnSubscribe(cancellable -> capture(CaptureSlot.ORIGINAL_ON_SUBSCRIBE)).beforeFinally(new TerminalSignalConsumer() {
@Override
public void onComplete() {
capture(CaptureSlot.ORIGINAL_ON_COMPLETE);
}
@Override
public void onError(final Throwable throwable) {
capture(CaptureSlot.ORIGINAL_ON_ERROR);
}
@Override
public void cancel() {
capture(CaptureSlot.OFFLOADED_CANCEL);
}
});
// Perform offloading and add more thread/context recording test points
Completable offloaded = offloadingFunction.apply(original, testExecutor.executor()).liftSync(subscriber -> {
capture(CaptureSlot.ORIGINAL_SUBSCRIBE);
return subscriber;
}).beforeOnSubscribe(cancellable -> capture(CaptureSlot.OFFLOADED_ON_SUBSCRIBE)).beforeFinally(new TerminalSignalConsumer() {
@Override
public void onComplete() {
capture(CaptureSlot.OFFLOADED_ON_COMPLETE);
}
@Override
public void onError(final Throwable throwable) {
capture(CaptureSlot.OFFLOADED_ON_ERROR);
}
@Override
public void cancel() {
capture(CaptureSlot.ORIGINAL_CANCEL);
}
});
// subscribe and generate terminal
toSource(offloaded).subscribe(testSubscriber);
assertThat("Unexpected tasks " + testExecutor.executor().queuedTasksPending(), testExecutor.executor().queuedTasksPending(), lessThan(2));
if (1 == testExecutor.executor().queuedTasksPending()) {
// execute offloaded subscribe
testExecutor.executor().executeNextTask();
}
Cancellable cancellable = testSubscriber.awaitSubscription();
assertThat("No Cancellable", cancellable, notNullValue());
testCompletable.awaitSubscribed();
assertThat("Source is not subscribed", testCompletable.isSubscribed());
assertThat("Thread was interrupted", !Thread.currentThread().isInterrupted());
switch(terminal) {
case CANCEL:
cancellable.cancel();
break;
case COMPLETE:
testCompletable.onComplete();
break;
case ERROR:
testCompletable.onError(DELIBERATE_EXCEPTION);
break;
default:
throw new AssertionError("unexpected terminal mode");
}
assertThat("Unexpected tasks " + testExecutor.executor().queuedTasksPending(), testExecutor.executor().queuedTasksPending(), lessThan(2));
if (1 == testExecutor.executor().queuedTasksPending()) {
// execute offloaded terminal
testExecutor.executor().executeNextTask();
}
} catch (Throwable all) {
AbstractOffloadingTest.LOGGER.warn("Unexpected throwable", all);
testSubscriber.onError(all);
}
};
APP_EXECUTOR_EXT.executor().execute(appCode);
// Ensure we reached the correct terminal condition
switch(terminal) {
case CANCEL:
testCancellable.awaitCancelled();
break;
case ERROR:
Throwable thrown = testSubscriber.awaitOnError();
assertThat("unexpected exception " + thrown, thrown, sameInstance(DELIBERATE_EXCEPTION));
break;
case COMPLETE:
testSubscriber.awaitOnComplete();
break;
default:
throw new AssertionError("unexpected terminal mode");
}
// Ensure that Async Context Map was correctly set during signals
ContextMap appMap = capturedContexts.captured(CaptureSlot.APP);
assertThat(appMap, notNullValue());
ContextMap subscribeMap = capturedContexts.captured(CaptureSlot.ORIGINAL_SUBSCRIBE);
assertThat(subscribeMap, notNullValue());
assertThat("Map was shared not copied", subscribeMap, not(sameInstance(appMap)));
assertThat("Missing custom async context entry ", subscribeMap.get(ASYNC_CONTEXT_CUSTOM_KEY), sameInstance(ASYNC_CONTEXT_VALUE));
EnumSet<CaptureSlot> checkSlots = EnumSet.complementOf(EnumSet.of(CaptureSlot.APP, CaptureSlot.ORIGINAL_SUBSCRIBE));
checkSlots.stream().filter(slot -> null != capturedContexts.captured(slot)).forEach(slot -> {
ContextMap map = capturedContexts.captured(slot);
assertThat("Context map was not captured", map, is(notNullValue()));
assertThat("Custom key missing from context map", map.containsKey(ASYNC_CONTEXT_CUSTOM_KEY));
assertThat("Unexpected context map @ slot " + slot + " : " + map, map, sameInstance(subscribeMap));
});
// Ensure that all offloading completed.
assertThat("Offloading pending", testExecutor.executor().queuedTasksPending(), is(0));
return testExecutor.executor().queuedTasksExecuted();
}
use of io.servicetalk.concurrent.api.Executor in project servicetalk by apple.
the class DefaultNettyConnectionTest method testConnectionDoesNotHoldAThread.
@Test
void testConnectionDoesNotHoldAThread() throws Exception {
AtomicInteger taskSubmitted = new AtomicInteger();
ExecutorService executor = java.util.concurrent.Executors.newCachedThreadPool();
try {
setupWithCloseHandler(ch -> forPipelinedRequestResponse(true, ch.config()), from(task -> {
taskSubmitted.incrementAndGet();
executor.submit(task);
}));
assertThat("Unexpected tasks submitted.", taskSubmitted.get(), is(0));
} finally {
executor.shutdownNow();
}
}
Aggregations