Search in sources :

Example 1 with Accumulator

use of io.servicetalk.concurrent.api.BufferStrategy.Accumulator in project servicetalk by apple.

the class PublisherBufferTest method subscriberThrowsFromOnNext.

@Test
void subscriberThrowsFromOnNext() {
    TestPublisher<Integer> tPublisher = new TestPublisher.Builder<Integer>().disableAutoOnSubscribe().build();
    TestPublisher<Accumulator<Integer, Integer>> bPublisher = new TestPublisher.Builder<Accumulator<Integer, Integer>>().disableAutoOnSubscribe().build();
    TestSubscription tSubscription = new TestSubscription();
    TestSubscription bSubscription = new TestSubscription();
    AtomicReference<TerminalNotification> terminal = new AtomicReference<>();
    AtomicInteger onNextCounter = new AtomicInteger();
    toSource(tPublisher.buffer(new TestBufferStrategy(bPublisher, BUFFER_SIZE_HINT))).subscribe(new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            s.request(MAX_VALUE);
        }

        @Override
        public void onNext(@Nullable Integer integer) {
            onNextCounter.incrementAndGet();
            throw DELIBERATE_EXCEPTION;
        }

        @Override
        public void onError(Throwable t) {
            terminal.set(error(t));
        }

        @Override
        public void onComplete() {
            terminal.set(complete());
        }
    });
    assertThat(tPublisher.isSubscribed(), is(true));
    tPublisher.onSubscribe(tSubscription);
    assertThat(bPublisher.isSubscribed(), is(true));
    bPublisher.onSubscribe(bSubscription);
    assertThat(tSubscription.requested(), is(0L));
    assertThat(bSubscription.requested(), is(MAX_VALUE));
    bPublisher.onNext(new SumAccumulator());
    assertThat((int) tSubscription.requested(), is(BUFFER_SIZE_HINT));
    tPublisher.onNext(1);
    bPublisher.onNext(new SumAccumulator());
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get().cause(), is(DELIBERATE_EXCEPTION));
    verifyCancelled(tSubscription);
    // Verify that further items are ignored
    terminal.set(null);
    tPublisher.onNext(2);
    bPublisher.onNext(new SumAccumulator());
    tPublisher.onComplete();
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get(), is(nullValue()));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 2 with Accumulator

use of io.servicetalk.concurrent.api.BufferStrategy.Accumulator in project servicetalk by apple.

the class PublisherBufferTest method originalSourceIsRetriedIfSubscriberThrows.

@Test
void originalSourceIsRetriedIfSubscriberThrows() {
    TestPublisher<Accumulator<Integer, Integer>> bPublisher = new TestPublisher<>();
    DelayedSubscription bSubscription = new DelayedSubscription();
    AtomicReference<TerminalNotification> terminal = new AtomicReference<>();
    BlockingQueue<Integer> items = new LinkedBlockingDeque<>();
    BlockingQueue<Integer> buffers = new LinkedBlockingDeque<>();
    AtomicInteger counter = new AtomicInteger();
    toSource(defer(() -> from(counter.incrementAndGet())).whenOnNext(items::add).retry((i, t) -> i < 3 && t == DELIBERATE_EXCEPTION).buffer(new TestBufferStrategy(bPublisher, 1))).subscribe(new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            bSubscription.delayedSubscription(s);
            bSubscription.request(1);
        }

        @Override
        public void onNext(@Nullable Integer integer) {
            assert integer != null;
            buffers.add(integer);
            throw DELIBERATE_EXCEPTION;
        }

        @Override
        public void onError(Throwable t) {
            terminal.set(error(t));
        }

        @Override
        public void onComplete() {
            terminal.set(complete());
        }
    });
    // it will generate a new boundary on each accumulation
    bPublisher.onNext(new SumAccumulator(bPublisher));
    assertThat(items, hasSize(1));
    assertThat(items, contains(1));
    assertThat(buffers, hasSize(1));
    assertThat(buffers, contains(1));
    bSubscription.request(MAX_VALUE);
    assertThat(items, hasSize(3));
    assertThat(items, contains(1, 2, 3));
    assertThat(buffers, hasSize(3));
    assertThat(buffers, contains(1, 2, 3));
    assertThat(terminal.get().cause(), is(DELIBERATE_EXCEPTION));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) Publisher.never(io.servicetalk.concurrent.api.Publisher.never) TerminalNotification.complete(io.servicetalk.concurrent.internal.TerminalNotification.complete) MAX_VALUE(java.lang.Long.MAX_VALUE) AtomicReference(java.util.concurrent.atomic.AtomicReference) Subscriber(io.servicetalk.concurrent.PublisherSource.Subscriber) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Matchers.nullValue(org.hamcrest.Matchers.nullValue) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) 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) Publisher.defer(io.servicetalk.concurrent.api.Publisher.defer) Nullable(javax.annotation.Nullable) Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) ValueSource(org.junit.jupiter.params.provider.ValueSource) TestPublisherSubscriber(io.servicetalk.concurrent.test.internal.TestPublisherSubscriber) Matchers.empty(org.hamcrest.Matchers.empty) BlockingQueue(java.util.concurrent.BlockingQueue) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) TerminalNotification.error(io.servicetalk.concurrent.internal.TerminalNotification.error) Test(org.junit.jupiter.api.Test) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Matchers.contains(org.hamcrest.Matchers.contains) Matchers.sameInstance(org.hamcrest.Matchers.sameInstance) Matcher(org.hamcrest.Matcher) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Matchers.is(org.hamcrest.Matchers.is) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 3 with Accumulator

use of io.servicetalk.concurrent.api.BufferStrategy.Accumulator in project servicetalk by apple.

the class PublisherBufferTest method subscriberThrowsFromOnNextBeforeTermination.

@Test
void subscriberThrowsFromOnNextBeforeTermination() {
    TestPublisher<Integer> tPublisher = new TestPublisher<>();
    TestPublisher<Accumulator<Integer, Integer>> bPublisher = new TestPublisher<>();
    TestSubscription bSubscription = new TestSubscription();
    AtomicReference<TerminalNotification> terminal = new AtomicReference<>();
    AtomicInteger onNextCounter = new AtomicInteger();
    toSource(tPublisher.buffer(new TestBufferStrategy(bPublisher, BUFFER_SIZE_HINT))).subscribe(new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            s.request(MAX_VALUE);
        }

        @Override
        public void onNext(@Nullable Integer integer) {
            onNextCounter.incrementAndGet();
            throw DELIBERATE_EXCEPTION;
        }

        @Override
        public void onError(Throwable t) {
            terminal.set(error(t));
        }

        @Override
        public void onComplete() {
            terminal.set(complete());
        }
    });
    assertThat(bPublisher.isSubscribed(), is(true));
    bPublisher.onSubscribe(bSubscription);
    assertThat(bSubscription.requested(), is(MAX_VALUE));
    bPublisher.onNext(new SumAccumulator());
    tPublisher.onNext(1);
    tPublisher.onComplete();
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get().cause(), is(DELIBERATE_EXCEPTION));
    verifyCancelled(bSubscription);
    // Verify that further items are ignored
    terminal.set(null);
    tPublisher.onNext(2);
    bPublisher.onNext(new SumAccumulator());
    tPublisher.onComplete();
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get(), is(nullValue()));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 4 with Accumulator

use of io.servicetalk.concurrent.api.BufferStrategy.Accumulator in project servicetalk by apple.

the class BufferStrategiesTest method sizeOrDurationConcurrent.

@Test
@Disabled("https://github.com/apple/servicetalk/issues/1259")
void sizeOrDurationConcurrent() throws Exception {
    final BlockingQueue<TestCompletable> timers = new LinkedBlockingDeque<>();
    final Executor executor = mock(Executor.class);
    when(executor.timer(any(Duration.class))).thenAnswer(invocation -> defer(() -> {
        TestCompletable timer = new TestCompletable();
        timers.add(timer);
        return timer;
    }));
    final int maxBoundaries = 1_000;
    final Collection<Integer> items = unmodifiableCollection(range(1, maxBoundaries).toFuture().get());
    final List<Integer> receivedFromBoundaries = new ArrayList<>(items.size());
    BufferStrategy<Integer, Accumulator<Integer, Iterable<Integer>>, Iterable<Integer>> strategy = forCountOrTime(1, ofDays(1), executor);
    CountDownLatch boundariesDone = new CountDownLatch(1);
    BlockingQueue<Accumulator<Integer, Iterable<Integer>>> boundaries = new LinkedBlockingQueue<>();
    BlockingQueue<Accumulator<Integer, Iterable<Integer>>> boundariesToFinish = new LinkedBlockingQueue<>();
    strategy.boundaries().beforeOnNext(boundaries::add).takeAtMost(maxBoundaries).afterFinally(boundariesDone::countDown).ignoreElements().subscribe();
    CyclicBarrier accumulateAndTimerStarted = new CyclicBarrier(2);
    Future<Object> timersFuture = EXEC.executor().submit(() -> {
        accumulateAndTimerStarted.await();
        while (boundariesDone.getCount() > 0) {
            timers.take().onComplete();
        }
        return null;
    }).toFuture();
    Future<Object> accumulateFuture = EXEC.executor().submit(() -> {
        accumulateAndTimerStarted.await();
        int boundariesReceived = 0;
        Iterator<Integer> itemsToPopulate = items.iterator();
        while (itemsToPopulate.hasNext()) {
            Accumulator<Integer, Iterable<Integer>> boundary = boundaries.take();
            if (++boundariesReceived < maxBoundaries) {
                boundary.accumulate(itemsToPopulate.next());
            } else {
                // add all items to the last boundary
                do {
                    boundary.accumulate(itemsToPopulate.next());
                } while (itemsToPopulate.hasNext());
            }
            boundariesToFinish.add(boundary);
        }
        return null;
    }).toFuture();
    boundariesDone.await();
    timersFuture.get();
    accumulateFuture.get();
    Accumulator<Integer, Iterable<Integer>> boundary;
    while ((boundary = boundariesToFinish.poll()) != null) {
        for (Integer item : boundary.finish()) {
            receivedFromBoundaries.add(item);
        }
    }
    assertThat("Unexpected items received.", receivedFromBoundaries, contains(items.toArray()));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Matchers.emptyIterable(org.hamcrest.Matchers.emptyIterable) ArrayList(java.util.ArrayList) Duration(java.time.Duration) CountDownLatch(java.util.concurrent.CountDownLatch) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ExecutorExtension.withCachedExecutor(io.servicetalk.concurrent.api.ExecutorExtension.withCachedExecutor) ExecutorExtension.withTestExecutor(io.servicetalk.concurrent.api.ExecutorExtension.withTestExecutor) Iterator(java.util.Iterator) Test(org.junit.jupiter.api.Test) Disabled(org.junit.jupiter.api.Disabled)

Example 5 with Accumulator

use of io.servicetalk.concurrent.api.BufferStrategy.Accumulator in project servicetalk by apple.

the class BufferStrategiesTest method boundariesEmittedAccordingToDemand.

@Test
void boundariesEmittedAccordingToDemand() throws Exception {
    CountDownLatch latch = new CountDownLatch(1);
    AtomicReference<TerminalNotification> terminated = new AtomicReference<>();
    AtomicInteger count = new AtomicInteger();
    final BlockingQueue<Throwable> asyncErrors = new LinkedBlockingDeque<>();
    toSource(forCountOrTime(2, ofMillis(1)).boundaries()).subscribe(new Subscriber<Accumulator<Object, Iterable<Object>>>() {

        private Subscription s;

        private int requested;

        @Override
        public void onSubscribe(final Subscription subscription) {
            s = subscription;
            requested++;
            s.request(1);
        }

        @Override
        public void onNext(@Nullable final Accumulator<Object, Iterable<Object>> accumulator) {
            try {
                assertThat("Unexpected accumulator", accumulator, is(notNullValue()));
                assertThat("Unexpected accumulation result", accumulator.finish(), emptyIterable());
            } catch (Throwable t) {
                asyncErrors.add(t);
            }
            count.incrementAndGet();
            if (requested++ < 5) {
                s.request(1);
            } else {
                s.cancel();
                latch.countDown();
            }
        }

        @Override
        public void onError(final Throwable t) {
            terminated.set(error(t));
            latch.countDown();
        }

        @Override
        public void onComplete() {
            terminated.set(complete());
            latch.countDown();
        }
    });
    latch.await();
    assertThat("Unexpected number of emitted accumulators", count.get(), is(5));
    assertThat("Unexpected termination", terminated.get(), is(nullValue()));
    assertNoAsyncErrors(asyncErrors);
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Matchers.emptyIterable(org.hamcrest.Matchers.emptyIterable) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test)

Aggregations

Accumulator (io.servicetalk.concurrent.api.BufferStrategy.Accumulator)6 Test (org.junit.jupiter.api.Test)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)4 DelayedSubscription (io.servicetalk.concurrent.internal.DelayedSubscription)4 TerminalNotification (io.servicetalk.concurrent.internal.TerminalNotification)4 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 CountDownLatch (java.util.concurrent.CountDownLatch)3 LinkedBlockingDeque (java.util.concurrent.LinkedBlockingDeque)3 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)3 TestPublisherSubscriber (io.servicetalk.concurrent.test.internal.TestPublisherSubscriber)2 Nullable (javax.annotation.Nullable)2 Matchers.emptyIterable (org.hamcrest.Matchers.emptyIterable)2 Subscriber (io.servicetalk.concurrent.PublisherSource.Subscriber)1 ExecutorExtension.withCachedExecutor (io.servicetalk.concurrent.api.ExecutorExtension.withCachedExecutor)1 ExecutorExtension.withTestExecutor (io.servicetalk.concurrent.api.ExecutorExtension.withTestExecutor)1 Publisher.defer (io.servicetalk.concurrent.api.Publisher.defer)1 Publisher.from (io.servicetalk.concurrent.api.Publisher.from)1 Publisher.never (io.servicetalk.concurrent.api.Publisher.never)1 SourceAdapters.toSource (io.servicetalk.concurrent.api.SourceAdapters.toSource)1