package reactor.spring.messaging; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.reactivestreams.Processor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.MessageBuilder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import reactor.bus.Event; import reactor.bus.EventBus; import reactor.spring.context.config.EnableReactor; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertTrue; /** * Comparing a Reactor {@code Processor}-backed Channel to a plain {@code Reactor}-backed Channel for comparing the net * effect of dynamic event routing on total throughput. It's pretty clear here that a simple Channel doesn't benefit * from the Reactor dynamic event dispatching and is better-suited to the single-task {@code Processor}. * * @author Jon Brisbin */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class ReactorSubscribableChannelThroughputTests { static final Logger LOG = LoggerFactory.getLogger(ReactorSubscribableChannelThroughputTests.class); static final int MSGS = 5000; @Autowired EventBus eventBus; CountDownLatch latch; long start; long end; double elapsed; int throughput; @Before public void init() { latch = new CountDownLatch(MSGS); } @After public void cleanup() { end = System.currentTimeMillis(); elapsed = end - start; throughput = (int)(MSGS / (elapsed / 1000)); LOG.info("Processed {} msgs in {}ms for throughput of {}/sec", MSGS, (long)elapsed, throughput); } @Test public void reactorSubscribableChannelMultiProducerThroughput() throws InterruptedException { doTest(new ReactorSubscribableChannel()); } @Test public void reactorSubscribableChannelSingleProducerThroughput() throws InterruptedException { doTest(new ReactorSubscribableChannel(true)); } private void doTest(ReactorSubscribableChannel channel) throws InterruptedException { channel.subscribe(new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { latch.countDown(); } }); Message<?> msg = MessageBuilder.withPayload("Hello World!").build(); start = System.currentTimeMillis(); for(int i = 0; i < MSGS; i++) { channel.send(msg); } assertTrue("latch did not time out", latch.await(5, TimeUnit.SECONDS)); } @Configuration @EnableReactor static class ReactorConfig { @Bean public EventBus eventBus(Processor<Event<?>, Event<?>> env) { return EventBus.create(env); } } }