Esempio n. 1
0
        public void MetricsChanged(ClusterMetricsChanged @event)
        {
            var oldValue        = _weightedRouteesRef.Value;
            var routees         = oldValue.Item1;
            var weightedRoutees = new WeightedRoutees(routees,
                                                      _cluster.SelfAddress,
                                                      _metricsSelector.Weights(@event.NodeMetrics).ToImmutableDictionary(pair => pair.Key, pair => pair.Value));

            // retry when CAS failure
            if (!_weightedRouteesRef.CompareAndSet(oldValue, Tuple.Create(routees, @event.NodeMetrics, weightedRoutees.AsOption())))
            {
                MetricsChanged(@event);
            }
        }
Esempio n. 2
0
        /// <inheritdoc />
        public override Routee Select(object message, Routee[] routees)
        {
            if (routees.Length == 0)
            {
                return(Routee.NoRoutee);
            }

            Option <WeightedRoutees> UpdateWeightedRoutees()
            {
                var oldValue = _weightedRouteesRef.Value;

                var(oldRoutees, oldMetrics, oldWeightedRoutees) = oldValue;

                if (oldRoutees.Equals(routees.ToImmutableArray()))
                {
                    return(oldWeightedRoutees);
                }

                var weightedRoutees = new WeightedRoutees(routees.ToImmutableArray(), _cluster.SelfAddress,
                                                          _metricsSelector.Weights(oldMetrics).ToImmutableDictionary(pair => pair.Key, pair => pair.Value));

                // ignore, don't update, in case of CAS failure
                _weightedRouteesRef.CompareAndSet(oldValue, Tuple.Create(routees.ToImmutableArray(), oldMetrics, weightedRoutees.AsOption()));
                return(weightedRoutees);
            }

            var updated = UpdateWeightedRoutees();

            if (updated.HasValue)
            {
                var weighted = updated.Value;
                if (weighted.IsEmpty)
                {
                    return(Routee.NoRoutee);
                }

                return(weighted[ThreadLocalRandom.Current.Next(weighted.Total) + 1]);
            }
            else
            {
                return(routees[ThreadLocalRandom.Current.Next(routees.Length)]);
            }
        }