Example #1
0
        public async Task ScaleUp(IEnumerable <EventData> events)
        {
            Guard.ArgumentNotNull(events, nameof(events));

            IEnumerable <string> collectionsToProcess = _cosmosDbThrottledEventsFilter.GetUniqueCosmosDBContainerNamesFromEventData(events);

            if (collectionsToProcess.IsNullOrEmpty())
            {
                return;
            }

            _logger.Information($"Found {collectionsToProcess.Count()} collections to process");

            foreach (string containerName in collectionsToProcess)
            {
                try
                {
                    CosmosCollectionType cosmosRepositoryType = containerName.GetEnumValueFromDescription <CosmosCollectionType>();

                    CosmosDbScalingCollectionSettings settings = await _scalingConfigRepositoryPolicy.ExecuteAsync(() =>
                                                                                                                   _cosmosDbScalingConfigRepository.GetCollectionSettingsByRepositoryType(cosmosRepositoryType));

                    int currentThroughput = settings.CurrentRequestUnits;

                    if (settings.AvailableRequestUnits == 0)
                    {
                        string errorMessage = $"The collection '{containerName}' throughput is already at the maximum of {settings.MaxRequestUnits} RU's";
                        _logger.Warning(errorMessage);
                        continue;
                    }

                    int incrementalRequestUnitsValue = scaleUpIncrementValue;

                    int increasedRequestUnits = currentThroughput + incrementalRequestUnitsValue;

                    if (incrementalRequestUnitsValue > settings.AvailableRequestUnits)
                    {
                        increasedRequestUnits = settings.MaxRequestUnits;

                        incrementalRequestUnitsValue = settings.AvailableRequestUnits;
                    }

                    settings.CurrentRequestUnits = await ScaleCollection(cosmosRepositoryType, increasedRequestUnits, settings.MaxRequestUnits);

                    await UpdateCollectionSettings(settings, CosmosDbScalingDirection.Up, incrementalRequestUnitsValue);
                }
                catch (NonRetriableException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    string errorMessage = $"Failed to increase cosmosdb request units on collection '{containerName}'";

                    _logger.Error(ex, errorMessage);

                    throw new RetriableException(errorMessage, ex);
                }
            }
        }
        public async Task <CosmosDbScalingConfig> GetConfigByRepositoryType(CosmosCollectionType cosmosCollectionType)
        {
            Guard.ArgumentNotNull(cosmosCollectionType, nameof(cosmosCollectionType));

            IQueryable <CosmosDbScalingConfig> configs = _cosmosRepository.Query <CosmosDbScalingConfig>().Where(x => x.RepositoryType == cosmosCollectionType);

            return(await Task.FromResult(configs.AsEnumerable().FirstOrDefault()));
        }
Example #3
0
        public async Task <CosmosDbScalingConfig> GetConfigByRepositoryType(CosmosCollectionType cosmosCollectionType)
        {
            Guard.ArgumentNotNull(cosmosCollectionType, nameof(cosmosCollectionType));

            IEnumerable <CosmosDbScalingConfig> configs = (await _cosmosRepository.Query <CosmosDbScalingConfig>(x => x.Content.RepositoryType == cosmosCollectionType));

            return(configs.FirstOrDefault());
        }
Example #4
0
        private async Task ScaleCollection(CosmosCollectionType cosmosRepositoryType, int requestUnits)
        {
            ICosmosDbScalingRepository cosmosDbScalingRepository = _cosmosDbScalingRepositoryProvider.GetRepository(cosmosRepositoryType);

            try
            {
                await _scalingRepositoryPolicy.ExecuteAsync(() => cosmosDbScalingRepository.SetThroughput(requestUnits));
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"Failed to set throughput on repository type '{cosmosRepositoryType}' with '{requestUnits}' request units");

                throw;
            }
        }
        public ICosmosDbScalingRepository GetRepository(CosmosCollectionType repositoryType)
        {
            switch (repositoryType)
            {
            case CosmosCollectionType.CalculationProviderResults:
                return(_serviceProvider.GetService <CalculationProviderResultsScalingRepository>());

            case CosmosCollectionType.ProviderSourceDatasets:
                return(_serviceProvider.GetService <ProviderSourceDatasetsScalingRepository>());

            case CosmosCollectionType.PublishedFunding:
                return(_serviceProvider.GetService <PublishedFundingScalingRepository>());

            case CosmosCollectionType.Calculations:
                return(_serviceProvider.GetService <CalculationsScalingRepository>());

            case CosmosCollectionType.Jobs:
                return(_serviceProvider.GetService <JobsScalingRepository>());

            case CosmosCollectionType.DatasetAggregations:
                return(_serviceProvider.GetService <DatasetAggregationsScalingRepository>());

            case CosmosCollectionType.Datasets:
                return(_serviceProvider.GetService <DatasetsScalingRepository>());

            case CosmosCollectionType.Profiling:
                return(_serviceProvider.GetService <ProfilingScalingRepository>());

            case CosmosCollectionType.Specifications:
                return(_serviceProvider.GetService <SpecificationsScalingRepository>());

            case CosmosCollectionType.TestResults:
                return(_serviceProvider.GetService <TestResultsScalingRepository>());

            case CosmosCollectionType.Tests:
                return(_serviceProvider.GetService <TestsScalingRepository>());

            case CosmosCollectionType.Users:
                return(_serviceProvider.GetService <UsersScalingRepository>());

            default:
                throw new ArgumentException("Invalid repository type provided");
            }
        }
Example #6
0
        public async Task <int> ScaleCollection(CosmosCollectionType cosmosRepositoryType, int requestUnits, int maxRequestUnits)
        {
            ICosmosDbScalingRepository cosmosDbScalingRepository = _cosmosDbScalingRepositoryProvider.GetRepository(cosmosRepositoryType);

            int throughPutRequestUnits = Math.Min(requestUnits, maxRequestUnits);

            try
            {
                await _scalingRepositoryPolicy.ExecuteAsync(async() => await cosmosDbScalingRepository.SetThroughput(throughPutRequestUnits));

                return(throughPutRequestUnits);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"Failed to set throughput on repository type '{cosmosRepositoryType}' with '{requestUnits}' request units");

                throw;
            }
        }
        public void GetRepository_GivenRepositoryType_ReturnsInstanceOfCorrectRepository(CosmosCollectionType cosmosRepositoryType, string repositoryTypeName)
        {
            //Arrange
            CosmosCollectionType repositoryType = cosmosRepositoryType;

            IServiceProvider serviceProvider = CreateServiceProvider();

            CosmosDbScalingRepositoryProvider scalingRepositoryProvider = new CosmosDbScalingRepositoryProvider(serviceProvider);

            //Act
            ICosmosDbScalingRepository scalingRepository = scalingRepositoryProvider.GetRepository(repositoryType);

            //Assert
            //AB: using gettype and name rather than assignable tp because ncrunch throws a wobbly
            scalingRepository
            .GetType()
            .Name
            .Should()
            .Be(repositoryTypeName);
        }
        public void GetRepository_GivenRepositoryTypeIsNotValid_ThrowsArgumentException()
        {
            //Arrange
            CosmosCollectionType repositoryType = (CosmosCollectionType)42;

            IServiceProvider serviceProvider = CreateServiceProvider();

            CosmosDbScalingRepositoryProvider scalingRepositoryProvider = new CosmosDbScalingRepositoryProvider(serviceProvider);

            //Act
            Action test = () => scalingRepositoryProvider.GetRepository(repositoryType);

            //Assert
            test
            .Should()
            .ThrowExactly <ArgumentException>()
            .Which
            .Message
            .Should()
            .Be("Invalid repository type provided");
        }
Example #9
0
        public async Task <CosmosDbScalingCollectionSettings> GetCollectionSettingsByRepositoryType(CosmosCollectionType cosmosCollectionType)
        {
            Guard.ArgumentNotNull(cosmosCollectionType, nameof(cosmosCollectionType));

            IEnumerable <CosmosDbScalingCollectionSettings> settings = (await _cosmosRepository.Query <CosmosDbScalingCollectionSettings>(x => x.Content.CosmosCollectionType == cosmosCollectionType));

            return(settings?.AsEnumerable().FirstOrDefault());
        }
Example #10
0
        private async Task <int?> GetMinimumThroughput(CosmosCollectionType collectionType)
        {
            ICosmosDbScalingRepository cosmosDbScalingRepository = _cosmosDbScalingRepositoryProvider.GetRepository(collectionType);

            return(await _scalingRepositoryPolicy.ExecuteAsync(async() => await cosmosDbScalingRepository.GetMinimumThroughput()));
        }