Exemplo n.º 1
0
        /// <summary>
        ///     Queues a message for sending to the hub for distribution.
        /// </summary>
        /// <param name="msg">Nyx message to send.</param>
        /// <param name="skip">Doesn't queue the message if no connection to the hub.</param>
        /// <returns>An observable for checking when the message is delivered to the Hub.</returns>
        public IObservable <MessageStatus> SendMessage(INyxMessage msg, bool skip = false)
        {
            if (msg == null)
            {
                return(Observable.Return(new MessageStatus(this, NyxMessage.EmptyOut, MessageCondition.Failed, "Null message")));
            }
            if (string.IsNullOrWhiteSpace(msg.Source))
            {
                msg.Source = NodeId;
            }
            if (string.IsNullOrWhiteSpace(msg.Target))
            {
                _logger.Error("Message validation failed, missing Target.");
                return(Observable.Return(new MessageStatus(this, msg, MessageCondition.Failed, "Message validation failed, missing Target.")));
            }
            // Processes internal messages like they were external messages.
            if (msg is InternalNyxMessage)
            {
                return(Observable.Start(() => ProcessExternalMessages(msg)));
            }
            if ((!_isConnected && !_queueOnDisconnected) || (!_hubOnline && skip) || (!_isConnected && skip))
            {
                _logger.Debug("Message missed. Not connected to any hub, or hub offline.");
                return(Observable.Return(new MessageStatus(this, msg, MessageCondition.Failed, "Not connected to any hub.")));
            }

            if (_messageLoopCancelation.IsCancellationRequested)
            {
                _logger.Error("Message missed. Not connected to any hub, or hub offline.");
                return(Observable.Return(new MessageStatus(this, msg, MessageCondition.Failed, "Borg is going down.")));
            }

            ((NyxMessage)msg).Direction = MessageDirection.Out;
            var observable = Observable.Create <MessageStatus>(observer =>
            {
                return(OutMessageStream.Where(m => m?.Message.Id == msg.Id).Subscribe(n =>
                {
                    observer.OnNext(n);
                    switch (n.Status)
                    {
                    case MessageCondition.Failed:
                    case MessageCondition.Filtered:
                    case MessageCondition.Sent:
                        observer.OnCompleted();
                        break;
                    }
                }));
            });

            lock (MessageQueueSync)
                _messageQueue.Enqueue(new MessageHelper {
                    Message = msg
                });
            _messageSendResetEvent.Set();

            return(observable);
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Protected default construtor for creating a new id.
        /// </summary>
        public NyxBorg(
            ILogger <NyxBorg> logger,
            IConfigManager config,
            PluginManager plugman)
        {
            NodeId  = Guid.NewGuid().ToString("N");
            _config = config;
            _logger = logger;
            _config.WhenConfigChanges.ObserveOn(ThreadPoolScheduler.Instance).Subscribe(LoadConfig);
            _plugman = plugman;

            _messageLoopToken  = _messageLoopCancelation.Token;
            _serverCancelToken = _serverCancelationSource.Token;

            _disposables.Add(_messageSendResetEvent);
            _disposables.Add(_serverEvent);
            _disposables.Add(_messageLoopCancelation);
            _disposables.Add(_serverCancelationSource);

            LoadConfig(null);
            Heartbeat.CreateInstance(_lastHubIp, _port);
            //_heartbeat = new Heartbeat(_context, _lastHubIp, _port.ToString());
            ConnectionStatusStream = Observable.Create <ConnectionStatus>(o =>
            {
                _logger.Debug("Hearbeat restarted.");
                Heartbeat.Instance.Init();
                return(Heartbeat.Instance.ConnectionStatusStream.Subscribe(o));
            }).Repeat().Publish().RefCount();

            _disposables.Add(ConnectionStatusStream
                             .ObserveOn(ThreadPoolScheduler.Instance)
                             .Subscribe(x => _hubOnline = x.HasFlag(ConnectionStatus.Online)));

            _disposables.Add(NyxMessageStream.Subscribe(x =>
            {
                if (TotalInMessages == long.MaxValue)
                {
                    TotalInMessages = 0;
                }
                TotalInMessages++;
            }));

            _disposables.Add(OutMessageStream.Subscribe(x =>
            {
                if (TotalInMessages == long.MaxValue)
                {
                    TotalOutMessages = 0;
                }
                TotalOutMessages++;
            }));
        }
Exemplo n.º 3
0
        /// <summary>
        ///     Server loop
        /// </summary>
        private void ServerLoop()
        {
            if (Thread.CurrentThread.Name == null)
            {
                Thread.CurrentThread.Name = "Nyx Borg Server Loop";
            }

            _logger.Debug("Starting borg server loop...");
            //_disposables.Add(NyxMessageStream.SubscribeOn(ThreadPoolScheduler.Instance).Subscribe(ReceivedMessage));

            _disposables.Add(NyxMessageStream
                             .TimeInterval()
                             .Do(t => _logger.Info("Last message ({1}) received {0:##0.000}s ago.", t.Interval.TotalSeconds, t.Value.Action))
                             .Select(t => new NyxMessage(t.Value as NyxMessage))
                             .ObserveOnPool()
                             .Subscribe(ReceivedMessage));

            _disposables.Add(OutMessageStream
                             .Where(m => m.Status == MessageCondition.Sent)
                             .TimeInterval()
                             .Do(t => _logger.Info("Last message ({1}) sent {0:##0.000}s ago.", t.Interval.TotalSeconds, t.Value.Message.Action))
                             .ObserveOnPool()
                             .Subscribe());

            var messageLoopTask = new Task(MessageSenderLoop, _messageLoopToken, TaskCreationOptions.LongRunning);

            messageLoopTask.Start();
            _plugman.StartAllPlugins();
            Status = NyxNodeStatus.Started;
            _nodeStatusSubject.OnNext(NyxNodeStatus.Started);

            // Endless loop until request to stop, then shutdowns
            while (!_serverCancelToken.IsCancellationRequested)
            {
                _serverEvent.WaitOne(6000);
            }
            _logger.Debug("Stopping server loop...");
            var stopTask = Task.Run(() => _plugman.StopAllPlugins(), _messageLoopToken);

            if (!stopTask.Wait(TimeSpan.FromSeconds(45)))
            {
                _logger.Error("Plugins didn't stop in the allocated time.");
            }
            // Dispose the event listener and no "leaks"

            // Flush any message leftovers
            _messageSendResetEvent.Set();
            if (_messageQueue.Count > 0)
            {
                Thread.Sleep(TimeSpan.FromSeconds(15));
                _messageSendResetEvent.Set();
            }
            _messageLoopCancelation.Cancel();
            _nodeConnectionSubject.OnNext(ConnectionStatus.Disconnected);

            Status = NyxNodeStatus.Stopped;
            _nodeStatusSubject.OnNext(Status);

            _actor?.Dispose();
            _connectionDisposable?.Dispose();
            _reqSocket?.Dispose();
            IsStarted = false;
        }