@Test public void testDefaultRequestTaskThreadName() { String mainName = "workQueueProcessorRequestTask"; String expectedName = mainName + "[request-task]"; WorkQueueProcessor<Object> processor = WorkQueueProcessor.builder().name(mainName).bufferSize(8).build(); processor.requestTask(Operators.cancelledSubscription()); Thread[] threads = new Thread[Thread.activeCount()]; Thread.enumerate(threads); //cleanup to avoid visibility in other tests processor.forceShutdown(); Condition<Thread> defaultRequestTaskThread = new Condition<>( thread -> thread != null && expectedName.equals(thread.getName()), "a thread named \"%s\"", expectedName); Assertions.assertThat(threads) .haveExactly(1, defaultRequestTaskThread); }
@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 testCustomRequestTaskThreadNameCreate() { String expectedName = "workQueueProcessorRequestTaskCreate"; //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 testForceShutdownAfterShutdown() throws InterruptedException { WorkQueueProcessor<String> processor = WorkQueueProcessor.<String>builder() .name("processor").bufferSize(4) .waitStrategy(WaitStrategy.phasedOffLiteLock(200, 100, TimeUnit.MILLISECONDS)) //eliminate the waitstrategy diff .build(); Publisher<String> publisher = Flux.fromArray(new String[] { "1", "2", "3", "4", "5" }); publisher.subscribe(processor); AssertSubscriber<String> subscriber = AssertSubscriber.create(0); processor.subscribe(subscriber); subscriber.request(1); Thread.sleep(250); processor.shutdown(); assertFalse(processor.awaitAndShutdown(Duration.ofMillis(400))); processor.forceShutdown(); assertTrue(processor.awaitAndShutdown(Duration.ofMillis(400))); }
@Override public Sink createSink(FlowConstruct flowConstruct, ReactiveProcessor function) { final long shutdownTimeout = flowConstruct.getMuleContext().getConfiguration().getShutdownTimeout(); WorkQueueProcessor<CoreEvent> processor = WorkQueueProcessor.<CoreEvent>builder().executor(ringBufferSchedulerSupplier.get()).bufferSize(bufferSize) .waitStrategy(waitStrategy.getReactorWaitStrategy()).build(); int subscriberCount = maxConcurrency < subscribers ? maxConcurrency : subscribers; CountDownLatch completionLatch = new CountDownLatch(subscriberCount); for (int i = 0; i < subscriberCount; i++) { processor.doOnSubscribe(subscription -> currentThread().setContextClassLoader(executionClassloader)).transform(function) .doFinally(s -> completionLatch.countDown()).subscribe(); } return new ReactorSink(processor.sink(), () -> { long start = currentTimeMillis(); if (!processor.awaitAndShutdown(ofMillis(shutdownTimeout))) { processor.forceShutdown(); } try { completionLatch.await(max(start - currentTimeMillis() + shutdownTimeout, 0l), MILLISECONDS); } catch (InterruptedException e) { currentThread().interrupt(); throw new MuleRuntimeException(e); } }, createOnEventConsumer(), bufferSize); }