public void Run(PairSocket shim) { _poller = new NetMQPoller(); _ = Observable.FromEventPattern <NetMQSocketEventArgs>(e => shim.ReceiveReady += e, e => shim.ReceiveReady -= e) .Select(e => e.EventArgs) .Subscribe(OnShimReady); _poller.Add(shim); // Timer var timeoutTimer = new NetMQTimer(TimeSpan.FromSeconds(5)); _ = Observable.FromEventPattern <NetMQTimerEventArgs>(e => timeoutTimer.Elapsed += e, e => timeoutTimer.Elapsed -= e) .Select(e => e.EventArgs) .ObserveOn(ThreadPoolScheduler.Instance) .Subscribe(OnTimeoutElapsed); _poller.Add(timeoutTimer); _subscriberSocket = new SubscriberSocket(); _subscriberSocket.Options.Linger = TimeSpan.Zero; _subscriberSocket.Subscribe(CoreHearbeatTopic); _subscriberSocket.Connect($"tcp://{_address}:{_port + 1}"); _subject.OnNext(ConnectionStatus.Connecting); _ = Observable.FromEventPattern <NetMQSocketEventArgs>(e => _subscriberSocket.ReceiveReady += e, e => _subscriberSocket.ReceiveReady -= e) .Select(e => e.EventArgs) .Where(e => e.Socket.ReceiveFrameString() == CoreHearbeatTopic) .ObserveOn(ThreadPoolScheduler.Instance) .Subscribe(e => { timeoutTimer.Reset(); Thread.MemoryBarrier(); var status = _borgConnected ? (ConnectionStatus.Online | ConnectionStatus.Connected) : (ConnectionStatus.Online | ConnectionStatus.Disconnected); _subject.OnNext(status); }); _poller.Add(_subscriberSocket); timeoutTimer.Reset(); shim.SignalOK(); _poller.Run(); // Cleanup stuff after stopping _poller.Remove(_subscriberSocket); _poller.Remove(timeoutTimer); _poller.Remove(shim); _poller.Dispose(); }
void IShimHandler.Run(PairSocket shim) { _poller = new NetMQPoller(); // Listen to actor dispose _ = Observable.FromEventPattern <NetMQSocketEventArgs>(e => shim.ReceiveReady += e, e => shim.ReceiveReady -= e) .Select(e => e.EventArgs) .ObserveOn(Scheduler.CurrentThread) .Subscribe(OnShimReady); _poller.Add(shim); _publisherSocket = new PublisherSocket(); _responseSocket = new RouterSocket(); #if MONITOR var monitor1 = new NetMQMonitor(_publisherSocket, "inproc://#monitor1", SocketEvents.All); _ = Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor1, "Connected") .Select(e => new { Event = "Connected", e }) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor1, nameof(monitor1.Listening)).Select(e => new { Event = "Listening", e })) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor1, nameof(monitor1.Accepted)).Select(e => new { Event = "Accepted", e })) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor1, nameof(monitor1.Closed)).Select(e => new { Event = "Closed", e })) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor1, nameof(monitor1.Disconnected)).Select(e => new { Event = "Disconnected", e })) .Do(e => _logger.Info("Monitor socket: {0}, {1}", e.Event, e.e.EventArgs.Address)) .Subscribe(); _ = Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor1, nameof(monitor1.AcceptFailed)) .Merge(Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor1, nameof(monitor1.ConnectDelayed))) .Merge(Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor1, nameof(monitor1.CloseFailed))) .Merge(Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor1, nameof(monitor1.BindFailed))) .Do(e => _logger.Error("Monitor error socket: {0}, {1}", e.EventArgs.ErrorCode, e.EventArgs.Address)) .Subscribe(); _ = Observable.FromEventPattern <NetMQMonitorIntervalEventArgs>(monitor1, nameof(monitor1.ConnectRetried)) .Do(e => _logger.Info("Monitor retry socket: {0}, {1}", e.EventArgs.Interval, e.EventArgs.Address)) .Subscribe(); monitor1.AttachToPoller(_poller); var monitor2 = new NetMQMonitor(_responseSocket, "inproc://#monitor2", SocketEvents.All); _ = Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor2, "Connected") .Select(e => new { Event = "Connected", e }) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor2, nameof(monitor2.Listening)).Select(e => new { Event = "Listening", e })) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor2, nameof(monitor2.Accepted)).Select(e => new { Event = "Accepted", e })) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor2, nameof(monitor2.Closed)).Select(e => new { Event = "Closed", e })) .Merge(Observable.FromEventPattern <NetMQMonitorSocketEventArgs>(monitor2, nameof(monitor2.Disconnected)).Select(e => new { Event = "Disconnected", e })) .Do(e => _logger.Info("Monitor socket: {0}, {1}", e.Event, e.e.EventArgs.Address)) .Subscribe(); _ = Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor2, nameof(monitor2.AcceptFailed)) .Merge(Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor2, nameof(monitor2.ConnectDelayed))) .Merge(Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor2, nameof(monitor2.CloseFailed))) .Merge(Observable.FromEventPattern <NetMQMonitorErrorEventArgs>(monitor2, nameof(monitor2.BindFailed))) .Do(e => _logger.Error("Monitor error socket: {0}, {1}", e.EventArgs.ErrorCode, e.EventArgs.Address)) .Subscribe(); _ = Observable.FromEventPattern <NetMQMonitorIntervalEventArgs>(monitor2, nameof(monitor2.ConnectRetried)) .Do(e => _logger.Info("Monitor retry socket: {0}, {1}", e.EventArgs.Interval, e.EventArgs.Address)) .Subscribe(); monitor2.AttachToPoller(_poller); #endif // To avoid crashes if the queue builds up too fast. _publisherSocket.Options.SendHighWatermark = 1000; _publisherSocket.Options.TcpKeepalive = true; _publisherSocket.Options.TcpKeepaliveIdle = TimeSpan.FromSeconds(5); _publisherSocket.Options.TcpKeepaliveInterval = TimeSpan.FromSeconds(1); // Number of network hops to jump, default is 1, which means local network. //_publisherSocket.Options.MulticastHops = 100; _publisherSocket.Bind($"tcp://*:{_port + 1}"); _poller.Add(_publisherSocket); _responseSocket.Bind($"tcp://*:{_port}"); _ = Observable.FromEventPattern <NetMQSocketEventArgs>( e => _responseSocket.ReceiveReady += e, e => _responseSocket.ReceiveReady -= e) .Select(e => e.EventArgs) .ObserveOn(Scheduler.CurrentThread) .Subscribe(e => { try { var msg = e.Socket.ReceiveMultipartMessage(); // Ignore messages that have less than 3 frames or no empty second frame. var address = msg.First(); var data = msg.Last().ConvertToString(); var nyxMsg = new NyxMessage().FromDefault(data); _messageSubject.OnNext(new Tuple <byte[], INyxMessage>(address.ToByteArray(), nyxMsg)); } catch (Exception ex) { _messageSubject.OnError(ex); } }); _poller.Add(_responseSocket); var heartbeatTimer = new NetMQTimer(TimeSpan.FromSeconds(2)); _ = Observable.FromEventPattern <NetMQTimerEventArgs>(e => heartbeatTimer.Elapsed += e, e => heartbeatTimer.Elapsed -= e) .Select(e => e.EventArgs) .Subscribe(OnTimeoutElapsed); _poller.Add(heartbeatTimer); heartbeatTimer.Reset(); shim.SignalOK(); _poller.Run(); #if MONITOR if (monitor1 != null) { monitor1.DetachFromPoller(); monitor2.DetachFromPoller(); } #endif _poller.Remove(_responseSocket); _poller.Remove(_publisherSocket); _poller.Remove(heartbeatTimer); _poller.Remove(shim); _poller.Dispose(); }