public void CascadeConfigurationWhenNecessary(IAutoscalingConfigurationSet configurationSet)
 {
     DemoMode = DemoMode.HasValue ? DemoMode : configurationSet.DemoMode;
     IncreaseInterval = IncreaseInterval.HasValue ? IncreaseInterval : configurationSet.IncreaseInterval;
     DecreaseInterval = DecreaseInterval.HasValue ? DecreaseInterval : configurationSet.DecreaseInterval;
     Reads.CascadeConfigurationWhenNecessary(configurationSet.Reads);
     Writes.CascadeConfigurationWhenNecessary(configurationSet.Writes);
 }
 protected AutoscalingConfigurationSet(IAutoscalingConfigurationSet configurationSet)
 {
     DemoMode = configurationSet.DemoMode;
     IncreaseInterval = configurationSet.IncreaseInterval;
     DecreaseInterval = configurationSet.DecreaseInterval;
     Reads = new AutoscalingConfiguration(configurationSet.Reads);
     Writes = new AutoscalingConfiguration(configurationSet.Writes);
 }
        public override async Task UpdateProvisionAsync(
            IAutoscalingConfigurationSet configuration,
            DynamoDbThroughput updated,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            await ThroughputClient.SetGlobalSecondaryIndexThroughputLevelAsync(
                tableName, indexName, updated.ReadThroughput, updated.WriteThroughput, cancellationToken)
                .ConfigureAwait(false);
        }
        public async Task ProvisionAsync(
            IAutoscalingConfigurationSet configuration,
            DynamoDbThroughput current,
            DynamoDbThroughput updated,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            var demoMode = configuration.DemoMode.GetValueOrDefault(true);
            var increaseInterval = TimeSpan.FromMinutes(configuration.IncreaseInterval.GetValueOrDefault(DefaultIncreaseInterval));
            var decreaseInterval = TimeSpan.FromMinutes(configuration.DecreaseInterval.GetValueOrDefault(DefaultDecreaseInterval));
            var readsEnabled = configuration.Reads.EnableAutoscaling.GetValueOrDefault(true);
            var writesEnabled = configuration.Writes.EnableAutoscaling.GetValueOrDefault(true);

            var shouldUpdateReads = ShouldUpdate(configuration.EntityName, "reads", current.ReadThroughput,
                updated.ReadThroughput, readsEnabled, demoMode, current.LastDecreaseAt, current.LastIncreaseAt, increaseInterval, decreaseInterval);
            if (!shouldUpdateReads)
                updated.ReadThroughput = current.ReadThroughput;
            
            var shouldUpdateWrites = ShouldUpdate(configuration.EntityName, "writes", current.WriteThroughput,
                updated.WriteThroughput, writesEnabled, demoMode, current.LastDecreaseAt, current.LastIncreaseAt, increaseInterval, decreaseInterval);
            if (!shouldUpdateWrites)
                updated.WriteThroughput = current.WriteThroughput;

            if (shouldUpdateReads || shouldUpdateWrites)
            {
                try
                {
                    await UpdateProvisionAsync(configuration, updated, cancellationToken);

                    StructuredLogger.Warning(
                        "{EntityName}: updating reads {CurrentReadThroughput}->{UpdatedReadThroughput}, writes {CurrentWriteThroughput}->{UpdatedWriteThroughput}",
                        configuration.EntityName, current.ReadThroughput, updated.ReadThroughput, current.WriteThroughput, updated.WriteThroughput);
                }
                catch (ResourceInUseException)
                {
                    StructuredLogger.Information("{EntityName}: still updating provision", configuration.EntityName);
                }
                catch (LimitExceededException)
                {
                    StructuredLogger.Information("{EntityName}: reached maximum decreases per day", configuration.EntityName);
                }
            }
            else
            {
                StructuredLogger.Information(
                    "{EntityName}: no changes reads {CurrentReadThroughput}, writes {CurrentWriteThroughput}",
                    configuration.EntityName, current.ReadThroughput, current.WriteThroughput);
            }
        }
 public abstract Task UpdateProvisionAsync(
     IAutoscalingConfigurationSet configuration,
     DynamoDbThroughput current,
     CancellationToken cancellationToken = default(CancellationToken));
 public TableAutoscalingConfigurationSet(string tableName, IAutoscalingConfigurationSet configurationSet)
     : base(configurationSet)
 {
     TableName = tableName;
 }
 public GlobalSecondaryIndexAutoscalingConfigurationSet(string tableName, string indexName, IAutoscalingConfigurationSet configurationSet)
     : base(tableName, configurationSet)
 {
     IndexName = indexName;
 }