コード例 #1
0
        public static IReadOnlyList <RedisClusterSize> ComputeShortestPath(RedisClusterSize from, RedisClusterSize to, Func <RedisClusterSize, IEnumerable <RedisClusterSize> > neighbors, Func <RedisClusterSize, RedisClusterSize, double> weight, IReadOnlyList <RedisClusterSize>?vertices = null)
        {
            if (from.Equals(to))
            {
                return(Array.Empty <RedisClusterSize>());
            }

            vertices ??= RedisClusterSize.Instances;
            var shortestPaths = ComputeOneToAllShortestPath(vertices, neighbors, weight, from);

            return(ComputeShortestPath(shortestPaths, from, to));
        }
コード例 #2
0
        /// <summary>
        /// This function embodies the concept of "how much does it cost to switch from
        /// <paramref name="current"/> to <paramref name="target"/>". At this point, we can assume that:
        ///     - The two input sizes are valid states to be in
        ///     - We can reach the target from current via some amount of autoscaling operations
        /// Hence, we're just ranking amonst the many potential states.
        /// </summary>
        public static double CostFunction(RedisClusterSize current, RedisClusterSize target, ModelContext modelContext, IReadOnlyDictionary <RedisClusterSize, RedisScalingUtilities.Node> shortestPaths)
        {
            // Switching to the same size (i.e. no op) is free
            if (current.Equals(target))
            {
                return(0);
            }

            var shortestPath = RedisScalingUtilities.ComputeShortestPath(shortestPaths, current, target);

            Contract.Assert(shortestPath.Count > 0);

            // Positive if we are spending more money, negative if we are saving
            return((double)(target.MonthlyCostUsd - current.MonthlyCostUsd));
        }
コード例 #3
0
        public static bool CanScale(RedisClusterSize from, RedisClusterSize to)
        {
            if (from.Equals(to))
            {
                return(true);
            }

            if (!CanScale(from.Tier, to.Tier))
            {
                return(false);
            }

            if (from.Shards != to.Shards && !from.Tier.Equals(to.Tier))
            {
                // Azure can't change both shards and tiers at once, we need to do them one at a time.
                return(false);
            }

            return(true);
        }
コード例 #4
0
        public static TimeSpan ExpectedScalingDelay(RedisClusterSize from, RedisClusterSize to)
        {
            Contract.Requires(CanScale(from, to));

            if (from.Equals(to))
            {
                return(TimeSpan.Zero);
            }

            if (from.Tier.Equals(to.Tier))
            {
                // The tier is the same, so autoscaling will be either adding or reducing shards
                var shardDelta = Math.Abs(from.Shards - to.Shards);
                return(TimeSpan.FromTicks(Constants.RedisScaleTimePerShard.Ticks * shardDelta));
            }
            else
            {
                // Tier changed, which means the number of shards didn't. However, we will take the same amount of time
                // as the amount of shards that need to change tier.
                Contract.Assert(from.Shards == to.Shards);
                return(TimeSpan.FromTicks(Constants.RedisScaleTimePerShard.Ticks * from.Shards));
            }
        }
コード例 #5
0
        public static IReadOnlyList <RedisClusterSize> ComputeShortestPath(IReadOnlyDictionary <RedisClusterSize, Node> shortestPaths, RedisClusterSize from, RedisClusterSize to)
        {
            if (from.Equals(to))
            {
                return(Array.Empty <RedisClusterSize>());
            }

            var path    = new List <Node>();
            var current = shortestPaths[to];

            while (current.Predecessor != null)
            {
                path.Add(current);
                current = current.Predecessor;
            }

            if (!current.ClusterSize.Equals(from))
            {
                return(Array.Empty <RedisClusterSize>());
            }

            path.Reverse();
            return(path.Select(p => p.ClusterSize).ToList());
        }