package io.muoncore.channel; import io.muoncore.channel.impl.StandardAsyncChannel; import io.muoncore.channel.impl.TimeoutChannel; import io.muoncore.channel.impl.WiretapChannel; import io.muoncore.channel.impl.ZipChannel; import io.muoncore.channel.support.Scheduler; import io.muoncore.message.MuonMessage; import io.muoncore.transport.client.RingBufferLocalDispatcher; import io.muoncore.transport.client.TransportMessageDispatcher; import reactor.Environment; import reactor.core.Dispatcher; import reactor.core.config.DispatcherType; import java.util.function.Function; public class Channels { static Dispatcher WORK_DISPATCHER = Environment.newDispatcher(32768, 200, DispatcherType.THREAD_POOL_EXECUTOR); public static Dispatcher EVENT_DISPATCHER = new RingBufferLocalDispatcher("channel", 32768); public static void shutdown() { // EVENT_DISPATCHER.shutdown(); // WORK_DISPATCHER.shutdown(); } public static ZipChannel zipChannel(String name) { return new ZipChannel(EVENT_DISPATCHER, name); } /** * Create a channel that will issue a timeout to the left if no messages come from the right within the period. */ public static TimeoutChannel timeout(Scheduler scheduler, long timeout) { return new TimeoutChannel(EVENT_DISPATCHER, scheduler, timeout); } /** * Create a channel that permits wiretap on the events moving across it. */ public static <X extends MuonMessage,Y extends MuonMessage> Channel<X, Y> wiretapChannel(TransportMessageDispatcher wiretapDispatch) { return new WiretapChannel<>(EVENT_DISPATCHER, wiretapDispatch); } /** * Create a channel that will perform async, in order dispatch between two processes. * @param leftname * @param rightname * @param <X> * @param <Y> * @return */ public static <X,Y> Channel<X, Y> channel(String leftname, String rightname) { return new StandardAsyncChannel<>(leftname, rightname, EVENT_DISPATCHER); } /** * A channel that expects to do significant work on one side of the channel, so is allocated a worker to allow async * and parallel processing without impacting overall event dispatch. Event order becomes non deterministic * and multiple events will be being dispatched concurrently. */ public static <X,Y> Channel<X, Y> workerChannel(String leftname, String rightname) { return new StandardAsyncChannel<>(leftname, rightname, WORK_DISPATCHER); } public static <X,Y> void connect(ChannelConnection<X, Y> right, ChannelConnection<Y, X> left) { assert right != null; assert left != null; left.receive(right::send); right.receive(left::send); } public static <LeftIn,LeftOut, RightIn, RightOut> void connectAndTransform(ChannelConnection<LeftOut, LeftIn> left, ChannelConnection<RightOut, RightIn> right, Function<LeftIn, RightOut> transformerLeftToRight, Function<RightIn, LeftOut> transformerRightToLeft) { left.receive( message -> { if (message == null) { right.shutdown(); return; } right.send(transformerLeftToRight.apply(message)); }); right.receive(message -> { if (message == null) { left.shutdown(); return; } left.send(transformerRightToLeft.apply(message)); }); } }