private void BuildReportFromMessage(INyxMessage message) { lock (NodesLock) { var added = message.Get <IEnumerable <NodeInfo> >(NodeManagerAdded); var removed = message.Get <IEnumerable <NodeInfo> >(NodeManagerRemoved); var cleanup = message.Get <bool>(NodeManagerCleanup); // Cache all nodes info on borg. if (cleanup) { _nodesInfo.Clear(); removed = new List <NodeInfo>(_nodesInfo); } else { _nodesInfo.RemoveAll(p => removed.Any(r => p?.NodeId == r.NodeId)); } var addedNodes = added as IList <NodeInfo> ?? added.ToList(); if (added != null) { _nodesInfo.RemoveAll(n => addedNodes.Any(o => o.NodeId == n.NodeId)); _nodesInfo.AddRange(addedNodes); } UpdateGroupInfo(); // Internal broadcast the info to the message bus, so ui can get the updates. var managerMessage = new NodesChanges { Added = addedNodes, Removed = removed, All = new List <NodeInfo>(_nodesInfo) }; _nodesSubject.OnNext(managerMessage); _groupSubject.OnNext(_groups.Clone()); } }
private void RunNodeCollector(INyxMessage message) { var info = message.Get <NodeInfo>(NodeManagerInfo); if (info == null) { return; } var sw = Stopwatch.StartNew(); using (Disposable.Create(() => { _logger.Trace("Hub node collector took {0}ms.", sw.ElapsedMilliseconds); sw.Stop(); })) { if (message.Action == NodesPingStop) { _logger.Debug("Received ping stop from {0}", StringExtensions.Trimmer(message.Source)); var indexToRemove = _nodesInfo.FindIndex(ni => ni.NodeId == message.Source); if (indexToRemove == -1) { return; } var nodeToRemove = _nodesInfo.ElementAt(indexToRemove); lock (NodesLock) _nodesInfo.RemoveAt(indexToRemove); lock (UpdaterLock) { foreach (var update in _pushUpdates) { SendNodesInfo(null, update, new List <NodeInfo>(), new[] { nodeToRemove }); } } return; } bool dirty = false; var removed = new List <NodeInfo>(); var added = new List <NodeInfo>(); var index = _nodesInfo.FindIndex(ni => ni.NodeId == info.NodeId); if (index == -1) { _nodesInfo.Add(info); lock (NodesLock) added.Add(info); } else { // Quick check for group changes dirty = _nodesInfo[index].GetHashCode() != info.GetHashCode(); if (dirty) { lock (NodesLock) added.Add(info); } _nodesInfo[index] = info; } // Cleanup 140 seconds old nodes that don't respond. lock (NodesLock) { _nodesInfo.RemoveAll(ni => { var res = DateTime.Now.Subtract(ni.TimeStamp).TotalSeconds > 140; if (res) { removed.Add(ni); } return(res); }); } // Remove dead subscriptions lock (UpdaterLock) _pushUpdates.RemoveWhere(p => _nodesInfo.All(ni => ni.NodeId != p)); message.Remove(NodeManagerInfo); // Push updates only if something changed. if (added.Count == 0 && removed.Count == 0 && !dirty) { return; } _logger.Debug("Added {0} nodes and removed {1}.", added.Count, removed.Count); lock (UpdaterLock) { foreach (var update in _pushUpdates) { SendNodesInfo(null, update, added, removed); } // Notify any hub plugin listening to node changes _nodesSubject.OnNext(new NodesChanges { All = _nodesInfo.AsReadOnly(), Added = added.AsReadOnly(), Removed = removed.AsReadOnly() }); _groupSubject.OnNext(_groups.Clone()); } } }