public ClusterMetricsCollector(IActorRef publisher)
        {
            _publisher = publisher;
            _cluster = Cluster.Get(Context.System);
            Collector = MetricsCollector.Get(Context.System.AsInstanceOf<ExtendedActorSystem>(), _cluster.Settings);
            LatestGossip = MetricsGossip.Empty;
            Nodes = ImmutableHashSet.Create<Address>();

            _metricsCancelable = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(
                _cluster.Settings.PeriodicTasksInitialDelay.Max(_cluster.Settings.MetricsInterval),
                _cluster.Settings.MetricsInterval, Self, InternalClusterAction.MetricsTick.Instance, Self);

            _gossipCancelable = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(
                _cluster.Settings.PeriodicTasksInitialDelay.Max(_cluster.Settings.GossipInterval), 
                _cluster.Settings.GossipInterval, Self, InternalClusterAction.GossipTick.Instance, Self);

            Receive<InternalClusterAction.GossipTick>(tick => Gossip());
            Receive<InternalClusterAction.MetricsTick>(tick => Collect());
            Receive<MetricsGossipEnvelope>(envelope => ReceiveGossip(envelope));
            Receive<ClusterEvent.CurrentClusterState>(state => ReceiveState(state));
            Receive<ClusterEvent.MemberUp>(up => AddMember(up.Member));
            Receive<ClusterEvent.MemberRemoved>(removed => RemoveMember(removed.Member));
            Receive<ClusterEvent.MemberExited>(exited => RemoveMember(exited.Member));
            Receive<ClusterEvent.UnreachableMember>(member => RemoveMember(member.Member));
            Receive<ClusterEvent.ReachableMember>(member =>
            {
                if (member.Member.Status == MemberStatus.Up) AddMember(member.Member);
            });
            Receive<ClusterEvent.IMemberEvent>(@event => { }); //not interested in other types of member event
        }
        public ClusterMetricsCollector(ActorRef publisher)
        {
            _publisher   = publisher;
            _cluster     = Cluster.Get(Context.System);
            Collector    = MetricsCollector.Get(Context.System.AsInstanceOf <ExtendedActorSystem>(), _cluster.Settings);
            LatestGossip = MetricsGossip.Empty;
            Nodes        = ImmutableHashSet.Create <Address>();

            _metricsTask = new CancellationTokenSource();
            Context.System.Scheduler.Schedule(_cluster.Settings.PeriodicTasksInitialDelay.Max(_cluster.Settings.MetricsInterval),
                                              _cluster.Settings.MetricsInterval, Self, InternalClusterAction.MetricsTick.Instance, _metricsTask.Token);

            _gossipTask = new CancellationTokenSource();
            Context.System.Scheduler.Schedule(_cluster.Settings.PeriodicTasksInitialDelay.Max(_cluster.Settings.GossipInterval),
                                              _cluster.Settings.GossipInterval, Self, InternalClusterAction.GossipTick.Instance, _gossipTask.Token);

            Receive <InternalClusterAction.GossipTick>(tick => Gossip());
            Receive <InternalClusterAction.MetricsTick>(tick => Collect());
            Receive <MetricsGossipEnvelope>(envelope => ReceiveGossip(envelope));
            Receive <ClusterEvent.CurrentClusterState>(state => ReceiveState(state));
            Receive <ClusterEvent.MemberUp>(up => AddMember(up.Member));
            Receive <ClusterEvent.MemberRemoved>(removed => RemoveMember(removed.Member));
            Receive <ClusterEvent.MemberExited>(exited => RemoveMember(exited.Member));
            Receive <ClusterEvent.UnreachableMember>(member => RemoveMember(member.Member));
            Receive <ClusterEvent.ReachableMember>(member =>
            {
                if (member.Member.Status == MemberStatus.Up)
                {
                    AddMember(member.Member);
                }
            });
            Receive <ClusterEvent.IMemberEvent>(@event => { }); //not interested in other types of member event
        }
        /// <summary>
        /// Receives changes from peer nodes, merges remote with local gossip nodes, then publishes
        /// changes to the event stream for load balancing router consumption, and gossip back.
        /// </summary>
        private void ReceiveGossip(MetricsGossipEnvelope envelope)
        {
            // remote node might not have same view of member nodes, this side should only care
            // about nodes that are known here, otherwise removed nodes can come back
            var otherGossip = envelope.Gossip.Filter(Nodes);

            LatestGossip = LatestGossip.Merge(otherGossip);
            // changes will be published in the period collect task
            if (!envelope.Reply)
            {
                ReplyGossipTo(envelope.From);
            }
        }
 public MetricsGossipEnvelope(Address @from, MetricsGossip gossip, bool reply)
 {
     Reply = reply;
     Gossip = gossip;
     From = @from;
 }
 private bool Equals(MetricsGossip other)
 {
     return Nodes.SequenceEqual(other.Nodes);
 }
 /// <summary>
 /// Adds new remote <see cref="NodeMetrics"/> and merges existing from a remote gossip.
 /// </summary>
 public MetricsGossip Merge(MetricsGossip otherGossip)
 {
     return otherGossip.Nodes.Aggregate(this, (gossip, metrics) => gossip + metrics);
 }
 /// <summary>
 /// Receives changes from peer nodes, merges remote with local gossip nodes, then publishes
 /// changes to the event stream for load balancing router consumption, and gossip back.
 /// </summary>
 private void ReceiveGossip(MetricsGossipEnvelope envelope)
 {
     // remote node might not have same view of member nodes, this side should only care
     // about nodes that are known here, otherwise removed nodes can come back
     var otherGossip = envelope.Gossip.Filter(Nodes);
     LatestGossip = LatestGossip.Merge(otherGossip);
     // changes will be published in the period collect task
     if (!envelope.Reply)
         ReplyGossipTo(envelope.From);
 }
 /// <summary>
 /// Samples the latest metrics for the node, updates metrics statistics in <see cref="MetricsGossip"/>, and
 /// publishes the changes to the event bus.
 /// </summary>
 private void Collect()
 {
     LatestGossip = LatestGossip + Collector.Sample();
     Publish();
 }
 /// <summary>
 /// Removes a member from the node ring.
 /// </summary>
 private void RemoveMember(Member member)
 {
     Nodes = Nodes.Remove(member.Address);
     LatestGossip = LatestGossip.Remove(member.Address);
 }
 public MetricsGossipEnvelope(Address @from, MetricsGossip gossip, bool reply)
 {
     Reply  = reply;
     Gossip = gossip;
     From   = @from;
 }
 private bool Equals(MetricsGossip other)
 {
     return(Nodes.SequenceEqual(other.Nodes));
 }
 /// <summary>
 /// Adds new remote <see cref="NodeMetrics"/> and merges existing from a remote gossip.
 /// </summary>
 public MetricsGossip Merge(MetricsGossip otherGossip)
 {
     return(otherGossip.Nodes.Aggregate(this, (gossip, metrics) => gossip + metrics));
 }
 /// <summary>
 /// Samples the latest metrics for the node, updates metrics statistics in <see cref="MetricsGossip"/>, and
 /// publishes the changes to the event bus.
 /// </summary>
 private void Collect()
 {
     LatestGossip = LatestGossip + Collector.Sample();
     Publish();
 }
 /// <summary>
 /// Removes a member from the node ring.
 /// </summary>
 private void RemoveMember(Member member)
 {
     Nodes        = Nodes.Remove(member.Address);
     LatestGossip = LatestGossip.Remove(member.Address);
 }