public async Task <bool> AttemptToScaleAsync(RuleContext context, RedisInstance redisInstance, CancellationToken cancellationToken) { Contract.Requires(redisInstance == _primaryRedisInstance || redisInstance == _secondaryRedisInstance); Contract.Requires(redisInstance.IsReadyToScale); // Fetch which cluster size we want, and start scaling operation if needed. var currentClusterSize = redisInstance.ClusterSize; var targetClusterSizeResult = await _redisAutoscalingAgent.EstimateBestClusterSizeAsync(redisInstance, cancellationToken); if (!targetClusterSizeResult.Succeeded) { Emit(context, "Autoscale", Severity.Error, $"Failed to find best plan for instance `{redisInstance.Name}` in plan `{currentClusterSize}`. Result=[{targetClusterSizeResult}]"); return(false); } var modelOutput = targetClusterSizeResult.Value; Contract.AssertNotNull(modelOutput); var targetClusterSize = modelOutput.TargetClusterSize; if (targetClusterSize.Equals(redisInstance.ClusterSize) || modelOutput.ScalePath.Count == 0) { // No autoscale required return(false); } Emit(context, "Autoscale", Severity.Warning, $"Autoscaling from `{currentClusterSize}` to `{targetClusterSize}` via scale path `{currentClusterSize} -> {string.Join(" -> ", modelOutput.ScalePath)}` for instance `{redisInstance.Name}`. Solution cost is `{modelOutput.Cost}`"); await redisInstance.ScaleAsync(modelOutput.ScalePath, cancellationToken).ThrowIfFailureAsync(); return(true); }
public async Task <Result <ModelOutput> > EstimateBestClusterSizeAsync(RedisInstance redisInstance, CancellationToken cancellationToken = default) { var now = DateTime.UtcNow; var redisAzureId = redisInstance.RedisCache.Id; var currentClusterSize = redisInstance.ClusterSize; var modelContext = await ComputeFeaturesAsync(now, redisAzureId, currentClusterSize, cancellationToken); return(Predict(currentClusterSize, modelContext)); }
public RedisAutoscalingRule(Configuration configuration, RedisAutoscalingAgent redisAutoscalingAgent, RedisInstance primaryRedisInstance, RedisInstance secondaryRedisInstance) : base(configuration) { Contract.Assert(primaryRedisInstance != secondaryRedisInstance); _configuration = configuration; _redisAutoscalingAgent = redisAutoscalingAgent; _primaryRedisInstance = primaryRedisInstance; _secondaryRedisInstance = secondaryRedisInstance; }