@Override public Promise<Void> shutdown() { final Deferred<Void, Promise<Void>> d = Promises.defer(env, getReactor().getDispatcher()); Reactors.schedule( new Consumer<Void>() { @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void accept(Void v) { final AtomicInteger groupsToShutdown = new AtomicInteger(2); GenericFutureListener listener = new GenericFutureListener() { @Override public void operationComplete(Future future) throws Exception { if (groupsToShutdown.decrementAndGet() == 0) { notifyShutdown(); d.accept((Void) null); } } }; selectorGroup.shutdownGracefully().addListener(listener); ioGroup.shutdownGracefully().addListener(listener); } }, null, getReactor()); return d.compose(); }
private void multipleRingBufferDispatchers() { Boundary b = new Boundary(); Reactor r1 = Reactors.reactor().env(env).dispatcher(Environment.RING_BUFFER).get(); Reactor r2 = Reactors.reactor().env(env).dispatcher(Environment.RING_BUFFER).get(); // Bind to a Selector using an anonymous object Tuple2<Selector, Object> anon = $(); r1.on(anon.getT1(), b.bind(consumer, 3)); r2.on(anon.getT1(), b.bind(consumer, 2)); r1.notify(anon.getT2(), Event.wrap(r1)); r1.notify(anon.getT2(), Event.wrap(r1)); r1.notify(anon.getT2(), Event.wrap(r1)); r2.notify(anon.getT2(), Event.wrap(r2)); r2.notify(anon.getT2(), Event.wrap(r2)); b.await(); }
@Test public void workerOrchestrator() throws InterruptedException { Reactor reactor = Reactors.reactor(env, Environment.WORK_QUEUE); CountDownLatch latch = new CountDownLatch(3); reactor.on( Selectors.$("worker"), new Consumer() { @Override public void accept(Object o) { System.out.println(Thread.currentThread().getName() + " worker " + o); reactor.notify("orchestrator", Event.wrap(1000)); latch.countDown(); System.out.println(Thread.currentThread().getName() + " ok"); } }); reactor.on( Selectors.$("orchestrator"), new Consumer<Event<Integer>>() { @Override public void accept(Event<Integer> event) { sendTask(); } void sendTask() { System.out.println(Thread.currentThread().getName() + " sendTask "); reactor.notify("worker", Event.wrap(latch.getCount())); latch.countDown(); } }); reactor.notify("orchestrator", Event.wrap(1000)); Assert.isTrue(latch.await(10, TimeUnit.SECONDS)); }
@Bean public Reactor threadPoolReactor(Environment env) { return Reactors.reactor().env(env).dispatcher(Environment.THREAD_POOL).get(); }
public static void main(String[] args) throws Exception { Environment env = new Environment(); final TradeServer server = new TradeServer(); // Use a Reactor to dispatch events using the high-speed Dispatcher final Reactor serverReactor = Reactors.reactor(env); // Create a single key and Selector for efficiency final Selector tradeExecute = Selectors.object("trade.execute"); // For each Trade event, execute that on the server and notify connected clients // because each client that connects links to the serverReactor serverReactor.on( tradeExecute, (Event<Trade> ev) -> { server.execute(ev.getData()); // Since we're async, for this test, use a latch to tell when we're done latch.countDown(); }); @SuppressWarnings("serial") WebSocketServlet wss = new WebSocketServlet() { @Override public void configure(WebSocketServletFactory factory) { factory.setCreator( (req, resp) -> new WebSocketListener() { AtomicLong counter = new AtomicLong(); @Override public void onWebSocketBinary(byte[] payload, int offset, int len) {} @Override public void onWebSocketClose(int statusCode, String reason) {} @Override public void onWebSocketConnect(final Session session) { LOG.info("Connected a websocket client: {}", session); // Keep track of a rolling average final AtomicReference<Float> avg = new AtomicReference<>(0f); serverReactor.on( tradeExecute, (Event<Trade> ev) -> { Trade t = ev.getData(); avg.set((avg.get() + t.getPrice()) / 2); // Send a message every 1000th trade. // Otherwise, we completely overwhelm the browser and network. if (counter.incrementAndGet() % 1000 == 0) { try { session .getRemote() .sendString(String.format("avg: %s", avg.get())); } catch (IOException e) { if (!"Failed to write bytes".equals(e.getMessage())) { e.printStackTrace(); } } } }); } @Override public void onWebSocketError(Throwable cause) {} @Override public void onWebSocketText(String message) {} }); } }; serve(wss); LOG.info( "Connect websocket clients now (waiting for 10 seconds).\n" + "Open websocket/src/main/webapp/ws.html in a browser..."); Thread.sleep(10000); // Start a throughput timer startTimer(); // Publish one event per trade for (int i = 0; i < totalTrades; i++) { // Pull next randomly-generated Trade from server Trade t = server.nextTrade(); // Notify the Reactor the event is ready to be handled serverReactor.notify(tradeExecute.getObject(), Event.wrap(t)); } // Stop throughput timer and output metrics endTimer(); server.stop(); }