Search in sources :

Example 11 with Executor

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();
    }
}
Also used : DefaultThreadFactory(io.servicetalk.concurrent.api.DefaultThreadFactory) HelloReply(io.grpc.examples.strategies.HelloReply) ServerContext(io.servicetalk.transport.api.ServerContext) GrpcExecutionStrategies.offloadNever(io.servicetalk.grpc.api.GrpcExecutionStrategies.offloadNever) Single(io.servicetalk.concurrent.api.Single) NoOffloadsRouteExecutionStrategy(io.servicetalk.router.api.NoOffloadsRouteExecutionStrategy) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) Greeter(io.grpc.examples.strategies.Greeter) GrpcServiceContext(io.servicetalk.grpc.api.GrpcServiceContext) GreeterService(io.grpc.examples.strategies.Greeter.GreeterService) GrpcExecutionStrategies.defaultStrategy(io.servicetalk.grpc.api.GrpcExecutionStrategies.defaultStrategy) GrpcExecutionStrategies(io.servicetalk.grpc.api.GrpcExecutionStrategies) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) GrpcExecutionStrategy(io.servicetalk.grpc.api.GrpcExecutionStrategy) Executor(io.servicetalk.concurrent.api.Executor) Executors(io.servicetalk.concurrent.api.Executors) AsyncCloseables(io.servicetalk.concurrent.api.AsyncCloseables) DefaultThreadFactory(io.servicetalk.concurrent.api.DefaultThreadFactory) GrpcServers(io.servicetalk.grpc.netty.GrpcServers) HelloRequest(io.grpc.examples.strategies.HelloRequest) Executor(io.servicetalk.concurrent.api.Executor) ServerContext(io.servicetalk.transport.api.ServerContext) Greeter(io.grpc.examples.strategies.Greeter) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable)

Example 12 with Executor

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();
}
Also used : Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) SERVICE_UNAVAILABLE(io.servicetalk.http.api.HttpResponseStatus.SERVICE_UNAVAILABLE) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) HttpServers.forAddress(io.servicetalk.http.netty.HttpServers.forAddress) Disabled(org.junit.jupiter.api.Disabled) Executors.from(io.servicetalk.concurrent.api.Executors.from) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) Executor(io.servicetalk.concurrent.api.Executor) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Nonnull(javax.annotation.Nonnull) HttpServerBuilder(io.servicetalk.http.api.HttpServerBuilder) Nullable(javax.annotation.Nullable) ValueSource(org.junit.jupiter.params.provider.ValueSource) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) ServerContext(io.servicetalk.transport.api.ServerContext) HttpClients.forSingleAddress(io.servicetalk.http.netty.HttpClients.forSingleAddress) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) AsyncCloseables.newCompositeCloseable(io.servicetalk.concurrent.api.AsyncCloseables.newCompositeCloseable) OK(io.servicetalk.http.api.HttpResponseStatus.OK) ConnectionAcceptorFactory.identity(io.servicetalk.transport.api.ConnectionAcceptorFactory.identity) ExecutionException(java.util.concurrent.ExecutionException) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) HttpExecutionStrategies.customStrategyBuilder(io.servicetalk.http.api.HttpExecutionStrategies.customStrategyBuilder) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) ConnectionRejectedException(io.servicetalk.client.api.ConnectionRejectedException) Matchers.is(org.hamcrest.Matchers.is) Matchers.anyOf(org.hamcrest.Matchers.anyOf) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) HttpServerBuilder(io.servicetalk.http.api.HttpServerBuilder) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy)

Example 13 with Executor

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();
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) BiFunction(java.util.function.BiFunction) Completable(io.servicetalk.concurrent.api.Completable) CoreMatchers.not(org.hamcrest.CoreMatchers.not) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) Cancellable(io.servicetalk.concurrent.Cancellable) TestCancellable(io.servicetalk.concurrent.api.TestCancellable) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) TestCompletableSubscriber(io.servicetalk.concurrent.test.internal.TestCompletableSubscriber) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) AbstractOffloadingTest(io.servicetalk.concurrent.api.internal.AbstractOffloadingTest) ContextMap(io.servicetalk.context.api.ContextMap) AsyncContext(io.servicetalk.concurrent.api.AsyncContext) TestCompletable(io.servicetalk.concurrent.api.TestCompletable) Matchers.lessThan(org.hamcrest.Matchers.lessThan) Executor(io.servicetalk.concurrent.api.Executor) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) EnumSet(java.util.EnumSet) CoreMatchers.sameInstance(org.hamcrest.CoreMatchers.sameInstance) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) Completable(io.servicetalk.concurrent.api.Completable) TestCompletable(io.servicetalk.concurrent.api.TestCompletable) Cancellable(io.servicetalk.concurrent.Cancellable) TestCancellable(io.servicetalk.concurrent.api.TestCancellable) ContextMap(io.servicetalk.context.api.ContextMap)

Example 14 with Executor

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();
    }
}
Also used : UNSUPPORTED_PROTOCOL_CLOSE_HANDLER(io.servicetalk.transport.netty.internal.CloseHandler.UNSUPPORTED_PROTOCOL_CLOSE_HANDLER) BeforeEach(org.junit.jupiter.api.BeforeEach) Protocol(io.servicetalk.transport.api.ConnectionInfo.Protocol) Arrays(java.util.Arrays) Charset.defaultCharset(java.nio.charset.Charset.defaultCharset) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) MAX_VALUE(java.lang.Integer.MAX_VALUE) TestCompletableSubscriber(io.servicetalk.concurrent.test.internal.TestCompletableSubscriber) Executors.from(io.servicetalk.concurrent.api.Executors.from) ExecutionStrategy.offloadAll(io.servicetalk.transport.api.ExecutionStrategy.offloadAll) ChannelPromise(io.netty.channel.ChannelPromise) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Matchers.nullValue(org.hamcrest.Matchers.nullValue) Executor(io.servicetalk.concurrent.api.Executor) Executors.immediate(io.servicetalk.concurrent.api.Executors.immediate) TestPublisherSubscriber(io.servicetalk.concurrent.test.internal.TestPublisherSubscriber) ChannelOutboundHandlerAdapter(io.netty.channel.ChannelOutboundHandlerAdapter) AbortedFirstWriteException(io.servicetalk.transport.netty.internal.WriteStreamSubscriber.AbortedFirstWriteException) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) ChannelOutboundBuffer(io.netty.channel.ChannelOutboundBuffer) Test(org.junit.jupiter.api.Test) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) Buffer(io.servicetalk.buffer.api.Buffer) Matchers.equalTo(org.hamcrest.Matchers.equalTo) FlushStrategies.defaultFlushStrategy(io.servicetalk.transport.netty.internal.FlushStrategies.defaultFlushStrategy) Matchers.is(org.hamcrest.Matchers.is) NoopConnectionObserver(io.servicetalk.transport.netty.internal.NoopTransportObserver.NoopConnectionObserver) Mockito.mock(org.mockito.Mockito.mock) Publisher.never(io.servicetalk.concurrent.api.Publisher.never) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) DEFAULT_ALLOCATOR(io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR) TestPublisher(io.servicetalk.concurrent.api.TestPublisher) Publisher(io.servicetalk.concurrent.api.Publisher) CloseHandler.forPipelinedRequestResponse(io.servicetalk.transport.netty.internal.CloseHandler.forPipelinedRequestResponse) Cancellable(io.servicetalk.concurrent.Cancellable) FlushStrategies.flushOnEnd(io.servicetalk.transport.netty.internal.FlushStrategies.flushOnEnd) Function(java.util.function.Function) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) FlushStrategies.batchFlush(io.servicetalk.transport.netty.internal.FlushStrategies.batchFlush) Matchers.hasSize(org.hamcrest.Matchers.hasSize) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) ExecutorService(java.util.concurrent.ExecutorService) ClosedChannelException(java.nio.channels.ClosedChannelException) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) Mockito.times(org.mockito.Mockito.times) Mockito.when(org.mockito.Mockito.when) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) Mockito.verify(org.mockito.Mockito.verify) US_ASCII(java.nio.charset.StandardCharsets.US_ASCII) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ExecutorService(java.util.concurrent.ExecutorService) Test(org.junit.jupiter.api.Test)

Aggregations

Executor (io.servicetalk.concurrent.api.Executor)14 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)7 Test (org.junit.jupiter.api.Test)7 Single (io.servicetalk.concurrent.api.Single)5 SourceAdapters.toSource (io.servicetalk.concurrent.api.SourceAdapters.toSource)5 Cancellable (io.servicetalk.concurrent.Cancellable)4 Completable (io.servicetalk.concurrent.api.Completable)4 Publisher (io.servicetalk.concurrent.api.Publisher)4 DEFAULT_ALLOCATOR (io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR)3 ConnectionRejectedException (io.servicetalk.client.api.ConnectionRejectedException)3 Executors (io.servicetalk.concurrent.api.Executors)3 ServerContext (io.servicetalk.transport.api.ServerContext)3 ExecutionException (java.util.concurrent.ExecutionException)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 Nullable (javax.annotation.Nullable)3 Matchers.is (org.hamcrest.Matchers.is)3 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 ChannelInboundHandlerAdapter (io.netty.channel.ChannelInboundHandlerAdapter)2 Buffer (io.servicetalk.buffer.api.Buffer)2 PublisherSource (io.servicetalk.concurrent.PublisherSource)2