@Test public void chainedWorkQueueProcessor() throws Exception{ ExecutorService es = Executors.newFixedThreadPool(2); try { WorkQueueProcessor<String> bc = WorkQueueProcessor.<String>builder().executor(es).bufferSize(16).build(); int elems = 18; CountDownLatch latch = new CountDownLatch(elems); bc.subscribe(TopicProcessorTest.sub("spec1", latch)); Flux.range(0, elems) .map(s -> "hello " + s) .subscribe(bc); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); } finally { es.shutdown(); } }
@Test public void forkJoinPoolWorkQueueRejectsSubscribers() { ExecutorService executorService = Executors.newWorkStealingPool(2); WorkQueueProcessor<String> bc = WorkQueueProcessor.<String>builder().executor(executorService).bufferSize(16).build(); CountDownLatch latch = new CountDownLatch(2); TestWorkQueueSubscriber spec1 = new TestWorkQueueSubscriber(latch, "spec1"); TestWorkQueueSubscriber spec2 = new TestWorkQueueSubscriber(latch, "spec2"); TestWorkQueueSubscriber spec3 = new TestWorkQueueSubscriber(latch, "spec3"); bc.subscribe(spec1); bc.subscribe(spec2); bc.subscribe(spec3); bc.onNext("foo"); bc.onComplete(); assertThat(spec1.error, is(nullValue())); assertThat(spec2.error, is(nullValue())); assertThat(spec3.error, is(notNullValue())); assertThat(spec3.error.getMessage(), is("The executor service could not accommodate another subscriber, detected limit 2")); try { latch.await(1, TimeUnit.SECONDS); } catch (InterruptedException e1) { fail(e1.toString()); } }
@Test(timeout = 4000) public void singleThreadWorkQueueSucceedsWithOneSubscriber() { ExecutorService executorService = Executors.newSingleThreadExecutor(); WorkQueueProcessor<String> bc = WorkQueueProcessor.<String>builder().executor(executorService).bufferSize(2).build(); CountDownLatch latch = new CountDownLatch(1); TestWorkQueueSubscriber spec1 = new TestWorkQueueSubscriber(latch, "spec1"); bc.subscribe(spec1); bc.onNext("foo"); bc.onNext("bar"); Executors.newSingleThreadScheduledExecutor() .schedule(bc::onComplete, 200, TimeUnit.MILLISECONDS); bc.onNext("baz"); try { latch.await(800, TimeUnit.MILLISECONDS); } catch (InterruptedException e1) { fail(e1.toString()); } assertNull(spec1.error); }
@Test public void fixedThreadPoolWorkQueueRejectsSubscribers() { ExecutorService executorService = Executors.newFixedThreadPool(2); WorkQueueProcessor<String> bc = WorkQueueProcessor.<String>builder().executor(executorService).bufferSize(16).build(); CountDownLatch latch = new CountDownLatch(3); TestWorkQueueSubscriber spec1 = new TestWorkQueueSubscriber(latch, "spec1"); TestWorkQueueSubscriber spec2 = new TestWorkQueueSubscriber(latch, "spec2"); TestWorkQueueSubscriber spec3 = new TestWorkQueueSubscriber(latch, "spec3"); bc.subscribe(spec1); bc.subscribe(spec2); bc.subscribe(spec3); bc.onNext("foo"); bc.onComplete(); assertThat(spec1.error, is(nullValue())); assertThat(spec2.error, is(nullValue())); assertThat(spec3.error, is(notNullValue())); assertThat(spec3.error.getMessage(), startsWith( "The executor service could not accommodate another subscriber, detected limit 2")); try { latch.await(1, TimeUnit.SECONDS); } catch (InterruptedException e1) { fail(e1.toString()); } }
@Test public void testCustomRequestTaskThreadNameShare() { String expectedName = "workQueueProcessorRequestTaskShare"; //NOTE: the below single executor should not be used usually as requestTask assumes it immediately gets executed ExecutorService customTaskExecutor = Executors.newSingleThreadExecutor(r -> new Thread(r, expectedName)); WorkQueueProcessor<Object> processor = WorkQueueProcessor.builder() .executor(Executors.newCachedThreadPool()) .requestTaskExecutor(customTaskExecutor) .bufferSize(8) .waitStrategy(WaitStrategy.liteBlocking()) .autoCancel(true) .build(); processor.requestTask(Operators.cancelledSubscription()); processor.subscribe(); Thread[] threads = new Thread[Thread.activeCount()]; Thread.enumerate(threads); //cleanup to avoid visibility in other tests customTaskExecutor.shutdownNow(); processor.forceShutdown(); Condition<Thread> customRequestTaskThread = new Condition<>( thread -> thread != null && expectedName.equals(thread.getName()), "a thread named \"%s\"", expectedName); Assertions.assertThat(threads) .haveExactly(1, customRequestTaskThread); }
@Test public void singleThreadWorkQueueDoesntRejectsSubscribers() { ExecutorService executorService = Executors.newSingleThreadExecutor(); WorkQueueProcessor<String> bc = WorkQueueProcessor.<String>builder().executor(executorService).bufferSize(2).build(); CountDownLatch latch = new CountDownLatch(1); TestWorkQueueSubscriber spec1 = new TestWorkQueueSubscriber(latch, "spec1"); TestWorkQueueSubscriber spec2 = new TestWorkQueueSubscriber(latch, "spec2"); bc.subscribe(spec1); bc.subscribe(spec2); bc.onNext("foo"); bc.onNext("bar"); Executors.newSingleThreadScheduledExecutor() .schedule(bc::onComplete, 200, TimeUnit.MILLISECONDS); try { bc.onNext("baz"); fail("expected 3rd next to time out as newSingleThreadExecutor cannot be introspected"); } catch (Throwable e) { assertTrue("expected AlertException, got " + e, WaitStrategy.isAlert(e)); } }
@Test public void createOverrideAll() { ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService requestTaskExecutor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WaitStrategy waitStrategy = WaitStrategy.busySpin(); boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .requestTaskExecutor(requestTaskExecutor) .bufferSize(bufferSize) .waitStrategy(waitStrategy) .autoCancel(autoCancel) .build(); assertProcessor(processor, false, null, bufferSize, waitStrategy, autoCancel, executor, requestTaskExecutor); }
@Test public void shareOverrideAll() { ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService requestTaskExecutor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WaitStrategy waitStrategy = WaitStrategy.busySpin(); boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .requestTaskExecutor(requestTaskExecutor) .bufferSize(bufferSize) .waitStrategy(waitStrategy) .autoCancel(autoCancel) .build(); assertProcessor(processor, true, null, bufferSize, waitStrategy, autoCancel, executor, requestTaskExecutor); }
@Test public void shareOverrideExecutorBufferSizeWaitStrategyAutoCancel() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WaitStrategy waitStrategy = WaitStrategy.busySpin(); boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .bufferSize(bufferSize) .waitStrategy(waitStrategy) .autoCancel(autoCancel) .build(); assertProcessor(processor, true, null, bufferSize, waitStrategy, autoCancel, executor, null); }
@Test public void createOverrideExecutorBufferSizeWaitStrategyAutoCancel() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WaitStrategy waitStrategy = WaitStrategy.busySpin(); boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .bufferSize(bufferSize) .waitStrategy(waitStrategy) .autoCancel(autoCancel) .build(); assertProcessor(processor, false, null, bufferSize, waitStrategy, autoCancel, executor, null); }
@Test public void shareOverrideExecutorBufferSizeWaitStrategy() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WaitStrategy waitStrategy = WaitStrategy.busySpin(); WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .bufferSize(bufferSize) .waitStrategy(waitStrategy) .build(); assertProcessor(processor, true, null, bufferSize, waitStrategy, null, executor, null); }
@Test public void shareOverrideExecutorBufferSizeAutoCancel() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .bufferSize(bufferSize) .autoCancel(autoCancel) .build(); assertProcessor(processor, true, null, bufferSize, null, autoCancel, executor, null); }
@Test public void shareOverrideExecutorBufferSize() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .bufferSize(bufferSize) .build(); assertProcessor(processor, true, null, bufferSize, null, null, executor, null); }
@Test public void createOverrideExecutor() { ExecutorService executor = Executors.newSingleThreadExecutor(); WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .build(); assertProcessor(processor, false, null, null, null, null, executor, null); }
@Test public void createOverrideExecutorBufferSizeWaitStrategy() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WaitStrategy waitStrategy = WaitStrategy.busySpin(); WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .bufferSize(bufferSize) .waitStrategy(waitStrategy) .build(); assertProcessor(processor, false, null, bufferSize, waitStrategy, null, executor, null); }
@Test public void createOverrideExecutorBufferSizeAutoCancel() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .bufferSize(bufferSize) .autoCancel(autoCancel) .build(); assertProcessor(processor, false, null, bufferSize, null, autoCancel, executor, null); }
@Test public void createOverrideExecutorAutoCancel() { ExecutorService executor = Executors.newSingleThreadExecutor(); boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .autoCancel(autoCancel) .build(); assertProcessor(processor, false, null, null, null, autoCancel, executor, null); }
@Test public void shareOverrideExecutor() { ExecutorService executor = Executors.newSingleThreadExecutor(); WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .build(); assertProcessor(processor, true, null, null, null, null, executor, null); }
@Test public void createOverrideExecutorBufferSize() { ExecutorService executor = Executors.newSingleThreadExecutor(); int bufferSize = 1024; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .executor(executor) .bufferSize(bufferSize) .build(); assertProcessor(processor, false, null, bufferSize, null, null, executor, null); }
@Test public void shareOverrideExecutorAutoCancel() { ExecutorService executor = Executors.newSingleThreadExecutor(); boolean autoCancel = false; WorkQueueProcessor<Integer> processor = WorkQueueProcessor.<Integer>builder() .share(true) .executor(executor) .autoCancel(autoCancel) .build(); assertProcessor(processor, true, null, null, null, autoCancel, executor, null); }