public void ValidateConstruction_WhenValidatorReturnsFalse_ShouldThrowArgumentNullExceptionWithListOfErrors()
        {
            // Arrange
            EngineSettings                nullEngineSettings               = Substitute.For <EngineSettings>();
            ICalculationsRepository       mockCalculationRepository        = Substitute.For <ICalculationsRepository>();
            ICalculatorResiliencePolicies mockCalculatorResiliencePolicies = Substitute.For <ICalculatorResiliencePolicies>();
            var mockMessengerPolicy = Policy.NoOpAsync();
            var mockProviderResultsRepositoryPolicy = Policy.NoOpAsync();

            mockCalculatorResiliencePolicies.CacheProvider.Returns((AsyncPolicy)null);
            mockCalculatorResiliencePolicies.Messenger.Returns(mockMessengerPolicy);
            mockCalculatorResiliencePolicies.ProviderSourceDatasetsRepository.Returns((AsyncPolicy)null);
            mockCalculatorResiliencePolicies.CalculationResultsRepository.Returns(mockProviderResultsRepositoryPolicy);
            mockCalculatorResiliencePolicies.CalculationsApiClient.Returns((AsyncPolicy)null);
            IValidator <ICalculatorResiliencePolicies> validator = new CalculatorResiliencePoliciesValidator();

            // Act
            Action validateAction = () =>
            {
                ICalculationEngineServiceValidator calculationEngineServiceValidator = new CalculationEngineServiceValidator(validator, nullEngineSettings, mockCalculatorResiliencePolicies, mockCalculationRepository);
            };

            // Assert
            validateAction
            .Should()
            .ThrowExactly <ArgumentNullException>()
            .And.Message
            .Should().Contain("CacheProvider")
            .And.Contain("ProviderSourceDatasetsRepository")
            .And.Contain("CalculationRepository");
        }
        public void Initialize()
        {
            _calculationEngine                = Substitute.For <ICalculationEngine>();
            _providersApiClient               = Substitute.For <IProvidersApiClient>();
            _specificationsApiClient          = Substitute.For <ISpecificationsApiClient>();
            _providerSourceDatasetsRepository = Substitute.For <IProviderSourceDatasetsRepository>();
            _calculationAggregationService    = Substitute.For <ICalculationAggregationService>();
            _calculationsRepository           = Substitute.For <ICalculationsRepository>();
            _logger = Substitute.For <ILogger>();
            _mapper = CreateMapper();

            _calculatorResiliencePolicies = new CalculatorResiliencePolicies
            {
                SpecificationsApiClient = Policy.NoOpAsync(),
                ProvidersApiClient      = Policy.NoOpAsync(),
                CalculationsApiClient   = Policy.NoOpAsync()
            };

            _calculationEnginePreviewService = new CalculationEnginePreviewService(
                _calculationEngine,
                _providersApiClient,
                _mapper,
                _calculatorResiliencePolicies,
                _specificationsApiClient,
                _providerSourceDatasetsRepository,
                _calculationAggregationService,
                _calculationsRepository,
                _logger);
        }
Example #3
0
        public ProviderResultsRepository(
            ICosmosRepository cosmosRepository,
            ILogger logger,
            IProviderResultCalculationsHashProvider calculationsHashProvider,
            ICalculatorResiliencePolicies calculatorResiliencePolicies,
            IResultsApiClient resultsApiClient,
            IJobManagement jobManagement)
        {
            Guard.ArgumentNotNull(cosmosRepository, nameof(cosmosRepository));
            Guard.ArgumentNotNull(logger, nameof(logger));
            Guard.ArgumentNotNull(calculationsHashProvider, nameof(calculationsHashProvider));
            Guard.ArgumentNotNull(calculatorResiliencePolicies, nameof(calculatorResiliencePolicies));
            Guard.ArgumentNotNull(resultsApiClient, nameof(resultsApiClient));
            Guard.ArgumentNotNull(calculatorResiliencePolicies.ResultsApiClient, nameof(calculatorResiliencePolicies.ResultsApiClient));
            Guard.ArgumentNotNull(jobManagement, nameof(jobManagement));

            _cosmosRepository = cosmosRepository;
            _logger           = logger;

            _calculationsHashProvider       = calculationsHashProvider;
            _resultsApiClient               = resultsApiClient;
            _resultsApiClientPolicy         = calculatorResiliencePolicies.ResultsApiClient;
            _calculationResultsCosmosPolicy = calculatorResiliencePolicies.CalculationResultsRepository;
            _jobManagement = jobManagement;
        }
        public void ValidateMessage_WhenMessageContainsAllComponents_ShouldNotThrowException()
        {
            // Arrange
            ILogger mockLogger = Substitute.For <ILogger>();

            const string cacheKey       = "Cache-key";
            const int    partitionIndex = 0;
            const int    partitionSize  = 100;

            Message message = new Message();
            IDictionary <string, object> messageUserProperties = message.UserProperties;

            messageUserProperties.Add(PartitionIndexKey, partitionIndex);
            messageUserProperties.Add(PartitionSizeKey, partitionSize);
            messageUserProperties.Add(PartitionCacheKeyKey, cacheKey);

            EngineSettings                mockEngineSettings               = Substitute.For <EngineSettings>();
            ICalculationsRepository       mockCalculationRepository        = Substitute.For <ICalculationsRepository>();
            ICalculatorResiliencePolicies mockCalculatorResiliencePolicies = Substitute.For <ICalculatorResiliencePolicies>();
            IValidator <ICalculatorResiliencePolicies> validator           = Substitute.For <IValidator <ICalculatorResiliencePolicies> >();
            ValidationResult result = new ValidationResult();

            validator.Validate(mockCalculatorResiliencePolicies)
            .Returns(result);

            ICalculationEngineServiceValidator calculationEngineServiceValidator = new CalculationEngineServiceValidator(validator, mockEngineSettings, mockCalculatorResiliencePolicies, mockCalculationRepository);

            // Act, Assert
            calculationEngineServiceValidator.ValidateMessage(mockLogger, message);
        }
Example #5
0
        public void SetUp()
        {
            _versionKeyProvider = Substitute.For <IProviderSourceDatasetVersionKeyProvider>();
            _fileSystemCache    = Substitute.For <IFileSystemCache>();
            _cosmosRepository   = Substitute.For <ICosmosRepository>();
            _resiliencePolicies = CalcEngineResilienceTestHelper.GenerateTestPolicies();

            _repository = new ProviderSourceDatasetsRepository(_cosmosRepository, _resiliencePolicies);

            _specificationId = "specId";
        }
        public ProviderSourceDatasetsRepository(ICosmosRepository cosmosRepository,
                                                ICalculatorResiliencePolicies calculatorResiliencePolicies
                                                )
        {
            Guard.ArgumentNotNull(cosmosRepository, nameof(cosmosRepository));
            Guard.ArgumentNotNull(calculatorResiliencePolicies, nameof(calculatorResiliencePolicies));
            Guard.ArgumentNotNull(calculatorResiliencePolicies.ProviderSourceDatasetsRepository, nameof(calculatorResiliencePolicies));

            _cosmosRepository = cosmosRepository;
            _providerSourceDatasetsRepositoryPolicy = calculatorResiliencePolicies.ProviderSourceDatasetsRepository;
        }
Example #7
0
        public void Initialize()
        {
            _mockLogger = Substitute.For <ILogger>();
            _mockSpecificationAssemblies = Substitute.For <ISpecificationAssemblyProvider>();
            _resiliencePolicies          = new CalculatorResiliencePolicies
            {
                CalculationsApiClient = Policy.NoOpAsync()
            };
            _mockCalculationsRepository = Substitute.For <ICalculationsRepository>();

            _assemblyService = new AssemblyService(_mockLogger, _mockSpecificationAssemblies, _resiliencePolicies, _mockCalculationsRepository);
        }
        public void ValidateConstruction_WhenEverythingIsSetupCorrectly_ShouldReturnWithoutThrowingException()
        {
            // Arrange
            EngineSettings                mockEngineSettings               = Substitute.For <EngineSettings>();
            ICalculationsRepository       mockCalculationRepository        = Substitute.For <ICalculationsRepository>();
            ICalculatorResiliencePolicies mockCalculatorResiliencePolicies = Substitute.For <ICalculatorResiliencePolicies>();
            IValidator <ICalculatorResiliencePolicies> validator           = Substitute.For <IValidator <ICalculatorResiliencePolicies> >();

            validator.Validate(mockCalculatorResiliencePolicies).Returns(new ValidationResult());

            // Act
            _ = new CalculationEngineServiceValidator(validator, mockEngineSettings, mockCalculatorResiliencePolicies, mockCalculationRepository);
        }
        private ProviderResultsRepository CreateProviderResultsRepository(
            ICosmosRepository cosmosRepository = null,
            ILogger logger = null,
            IProviderResultCalculationsHashProvider calculationsHashProvider = null,
            ICalculatorResiliencePolicies calculatorResiliencePolicies       = null,
            IJobManagement jobManagement = null) =>
        new ProviderResultsRepository(
            cosmosRepository ?? CreateCosmosRepository(),
            logger ?? CreateLogger(),

            calculationsHashProvider ?? CreateCalcHashProvider(),
            calculatorResiliencePolicies ?? CreateCalculatorResiliencePolicies(),
            _resultsApiClient,
            jobManagement ?? CreateJobManagement());
Example #10
0
        public SpecificationAssemblyProvider(IFileSystemCache fileSystemCache,
                                             IBlobClient blobs,
                                             ICalculatorResiliencePolicies resiliencePolicies,
                                             ILogger logger)
        {
            Guard.ArgumentNotNull(fileSystemCache, nameof(fileSystemCache));
            Guard.ArgumentNotNull(blobs, nameof(blobs));
            Guard.ArgumentNotNull(logger, nameof(logger));
            Guard.ArgumentNotNull(resiliencePolicies?.BlobClient, nameof(resiliencePolicies.BlobClient));

            _fileSystemCache = fileSystemCache;
            _blobs           = blobs;
            _logger          = logger;
            _blobResilience  = resiliencePolicies.BlobClient;
        }
Example #11
0
        public CalculationEngineServiceValidator(
            IValidator <ICalculatorResiliencePolicies> calculatorResiliencePoliciesValidator,
            EngineSettings engineSettings,
            ICalculatorResiliencePolicies resiliencePolicies,
            ICalculationsRepository calculationsRepository)
        {
            Guard.ArgumentNotNull(engineSettings, nameof(engineSettings));
            Guard.ArgumentNotNull(resiliencePolicies, nameof(resiliencePolicies));
            Guard.ArgumentNotNull(calculationsRepository, nameof(calculationsRepository));

            ValidationResult validationResult = calculatorResiliencePoliciesValidator.Validate(resiliencePolicies);

            if (!validationResult.IsValid)
            {
                throw new ArgumentNullException(null, string.Join(",", validationResult.Errors));
            }
        }
        public void Initialize()
        {
            _mockCacheProvider = Substitute.For <ICacheProvider>();
            _mockDatasetAggregationsRepository = Substitute.For <IDatasetAggregationsRepository>();
            _mockResiliencePolicies            = new CalculatorResiliencePolicies
            {
                CacheProvider = Policy.NoOpAsync()
            };

            engineSettings = new EngineSettings();

            _calculationAggregationService = new CalculationAggregationService(
                _mockCacheProvider,
                _mockDatasetAggregationsRepository,
                engineSettings,
                _mockResiliencePolicies);
        }
        public AssemblyService(
            ILogger logger,
            ISpecificationAssemblyProvider specificationAssemblies,
            ICalculatorResiliencePolicies resiliencePolicies,
            ICalculationsRepository calculationsRepository)
        {
            Guard.ArgumentNotNull(logger, nameof(logger));
            Guard.ArgumentNotNull(specificationAssemblies, nameof(specificationAssemblies));
            Guard.ArgumentNotNull(resiliencePolicies, nameof(resiliencePolicies));
            Guard.ArgumentNotNull(resiliencePolicies.CalculationsApiClient, nameof(resiliencePolicies.CalculationsApiClient));
            Guard.ArgumentNotNull(calculationsRepository, nameof(calculationsRepository));

            _logger = logger;
            _specificationAssemblies     = specificationAssemblies;
            _calculationsRepository      = calculationsRepository;
            _calculationsApiClientPolicy = resiliencePolicies.CalculationsApiClient;
        }
        public CalculationAggregationService(
            ICacheProvider cacheProvider,
            IDatasetAggregationsRepository datasetAggregationsRepository,
            EngineSettings engineSettings,
            ICalculatorResiliencePolicies resiliencePolicies)
        {
            Guard.ArgumentNotNull(cacheProvider, nameof(cacheProvider));
            Guard.ArgumentNotNull(datasetAggregationsRepository, nameof(datasetAggregationsRepository));
            Guard.ArgumentNotNull(engineSettings, nameof(engineSettings));
            Guard.ArgumentNotNull(resiliencePolicies, nameof(resiliencePolicies));
            Guard.ArgumentNotNull(resiliencePolicies.CacheProvider, nameof(resiliencePolicies.CacheProvider));

            _cacheProvider = cacheProvider;
            _datasetAggregationsRepository = datasetAggregationsRepository;
            _engineSettings      = engineSettings;
            _cacheProviderPolicy = resiliencePolicies.CacheProvider;
        }
        public CalculationEngineService(
            ILogger logger,
            ICalculationEngine calculationEngine,
            ICacheProvider cacheProvider,
            IMessengerService messengerService,
            IProviderSourceDatasetsRepository providerSourceDatasetsRepository,
            ITelemetry telemetry,
            IProviderResultsRepository providerResultsRepository,
            ICalculationsRepository calculationsRepository,
            EngineSettings engineSettings,
            ICalculatorResiliencePolicies resiliencePolicies,
            IValidator <ICalculatorResiliencePolicies> calculatorResiliencePoliciesValidator,
            IDatasetAggregationsRepository datasetAggregationsRepository,
            IFeatureToggle featureToggle,
            IJobsApiClient jobsApiClient)
        {
            _calculatorResiliencePoliciesValidator = calculatorResiliencePoliciesValidator;

            CalculationEngineServiceValidator.ValidateConstruction(_calculatorResiliencePoliciesValidator,
                                                                   engineSettings, resiliencePolicies, calculationsRepository);

            _logger            = logger;
            _calculationEngine = calculationEngine;
            _cacheProvider     = cacheProvider;
            _messengerService  = messengerService;
            _providerSourceDatasetsRepository = providerSourceDatasetsRepository;
            _telemetry = telemetry;
            _providerResultsRepository = providerResultsRepository;
            _calculationsRepository    = calculationsRepository;
            _engineSettings            = engineSettings;
            _cacheProviderPolicy       = resiliencePolicies.CacheProvider;
            _messengerServicePolicy    = resiliencePolicies.Messenger;
            _providerSourceDatasetsRepositoryPolicy = resiliencePolicies.ProviderSourceDatasetsRepository;
            _providerResultsRepositoryPolicy        = resiliencePolicies.ProviderResultsRepository;
            _calculationsRepositoryPolicy           = resiliencePolicies.CalculationsRepository;
            _datasetAggregationsRepository          = datasetAggregationsRepository;
            _featureToggle       = featureToggle;
            _jobsApiClient       = jobsApiClient;
            _jobsApiClientPolicy = resiliencePolicies.JobsApiClient;
        }
        public void ValidateMessage_WhenPartitionSizeIsLessThanZero_ShouldThrowException()
        {
            // Arrange
            ILogger mockLogger = Substitute.For <ILogger>();

            const int    partitionSize  = -1;
            const int    partitionIndex = 0;
            const string cacheKey       = "Cache-key";

            Message message = new Message();
            IDictionary <string, object> messageUserProperties = message.UserProperties;

            messageUserProperties.Add(PartitionIndexKey, partitionIndex);
            messageUserProperties.Add(PartitionSizeKey, partitionSize);
            messageUserProperties.Add(PartitionCacheKeyKey, cacheKey);
            EngineSettings                mockEngineSettings               = Substitute.For <EngineSettings>();
            ICalculationsRepository       mockCalculationRepository        = Substitute.For <ICalculationsRepository>();
            ICalculatorResiliencePolicies mockCalculatorResiliencePolicies = Substitute.For <ICalculatorResiliencePolicies>();
            IValidator <ICalculatorResiliencePolicies> validator           = Substitute.For <IValidator <ICalculatorResiliencePolicies> >();
            ValidationResult result = new ValidationResult();

            validator.Validate(mockCalculatorResiliencePolicies)
            .Returns(result);

            // Act
            Action validateMethod = () =>
            {
                ICalculationEngineServiceValidator calculationEngineServiceValidator = new CalculationEngineServiceValidator(validator, mockEngineSettings, mockCalculatorResiliencePolicies, mockCalculationRepository);
                calculationEngineServiceValidator.ValidateMessage(mockLogger, message);
            };

            // Assert
            validateMethod
            .Should()
            .ThrowExactly <KeyNotFoundException>()
            .And.Message
            .Should()
            .BeEquivalentTo(GeneratePartitionSizeErrorMessage(partitionSize));
        }
        public void ValidateMessage_WhenMessageDoesNotContainProviderCacheKey_ShouldThrowException()
        {
            // Arrange
            ILogger mockLogger = Substitute.For <ILogger>();

            const int partitionSize  = 100;
            const int partitionIndex = 0;

            Message message = new Message();
            IDictionary <string, object> messageUserProperties = message.UserProperties;

            messageUserProperties.Add(PartitionIndexKey, partitionIndex);
            messageUserProperties.Add(PartitionSizeKey, partitionSize);
            EngineSettings                mockEngineSettings               = Substitute.For <EngineSettings>();
            ICalculationsRepository       mockCalculationRepository        = Substitute.For <ICalculationsRepository>();
            ICalculatorResiliencePolicies mockCalculatorResiliencePolicies = Substitute.For <ICalculatorResiliencePolicies>();
            IValidator <ICalculatorResiliencePolicies> validator           = Substitute.For <IValidator <ICalculatorResiliencePolicies> >();
            ValidationResult result = new ValidationResult();

            validator.Validate(mockCalculatorResiliencePolicies)
            .Returns(result);

            // Act
            Action validateMethod = () =>
            {
                ICalculationEngineServiceValidator calculationEngineServiceValidator = new CalculationEngineServiceValidator(validator, mockEngineSettings, mockCalculatorResiliencePolicies, mockCalculationRepository);
                calculationEngineServiceValidator.ValidateMessage(mockLogger, message);
            };

            // Assert
            validateMethod
            .Should()
            .ThrowExactly <KeyNotFoundException>()
            .And.Message
            .Should()
            .BeEquivalentTo("Provider cache key not found");
        }
Example #18
0
        public CalculationEnginePreviewService(
            ICalculationEngine calculationEngine,
            IProvidersApiClient providersApiClient,
            IMapper mapper,
            ICalculatorResiliencePolicies resiliencePolicies,
            ISpecificationsApiClient specificationsApiClient,
            IProviderSourceDatasetsRepository providerSourceDatasetsRepository,
            ICalculationAggregationService calculationAggregationService,
            ICalculationsRepository calculationsRepository,
            ILogger logger)
        {
            Guard.ArgumentNotNull(calculationEngine, nameof(calculationEngine));
            Guard.ArgumentNotNull(providersApiClient, nameof(providersApiClient));
            Guard.ArgumentNotNull(mapper, nameof(mapper));
            Guard.ArgumentNotNull(providerSourceDatasetsRepository, nameof(providerSourceDatasetsRepository));
            Guard.ArgumentNotNull(calculationAggregationService, nameof(calculationAggregationService));
            Guard.ArgumentNotNull(calculationsRepository, nameof(calculationsRepository));
            Guard.ArgumentNotNull(logger, nameof(logger));

            Guard.ArgumentNotNull(resiliencePolicies, nameof(resiliencePolicies));
            Guard.ArgumentNotNull(resiliencePolicies.SpecificationsApiClient, nameof(resiliencePolicies.SpecificationsApiClient));
            Guard.ArgumentNotNull(resiliencePolicies.ProvidersApiClient, nameof(resiliencePolicies.ProvidersApiClient));
            Guard.ArgumentNotNull(resiliencePolicies.CalculationsApiClient, nameof(resiliencePolicies.CalculationsApiClient));

            _calculationEngine                = calculationEngine;
            _providersApiClient               = providersApiClient;
            _mapper                           = mapper;
            _specificationsApiClient          = specificationsApiClient;
            _providerSourceDatasetsRepository = providerSourceDatasetsRepository;
            _calculationAggregationService    = calculationAggregationService;
            _specificationsApiPolicy          = resiliencePolicies.SpecificationsApiClient;
            _providersApiClientPolicy         = resiliencePolicies.ProvidersApiClient;
            _calculationsApiClientPolicy      = resiliencePolicies.CalculationsApiClient;
            _calculationsRepository           = calculationsRepository;
            _logger                           = logger;
        }
        public void ValidateConstruction_WhenEngineSettingsIsNull_ShouldThrowException()
        {
            // Arrange
            EngineSettings                nullEngineSettings               = null;
            ICalculationsRepository       mockCalculationRepository        = Substitute.For <ICalculationsRepository>();
            ICalculatorResiliencePolicies mockCalculatorResiliencePolicies = Substitute.For <ICalculatorResiliencePolicies>();
            IValidator <ICalculatorResiliencePolicies> validator           = Substitute.For <IValidator <ICalculatorResiliencePolicies> >();

            validator.Validate(mockCalculatorResiliencePolicies).Returns(new ValidationResult());

            // Act
            Action validateAction = () =>
            {
                ICalculationEngineServiceValidator calculationEngineServiceValidator = new CalculationEngineServiceValidator(validator, nullEngineSettings, mockCalculatorResiliencePolicies, mockCalculationRepository);
            };

            // Assert
            validateAction
            .Should()
            .ThrowExactly <ArgumentNullException>()
            .And.Message
            .Should()
            .Contain("Parameter 'engineSettings'");
        }
        private static IServiceProvider Register(IServiceCollection builder, IConfigurationRoot config)
        {
            builder.AddSingleton <IUserProfileProvider, UserProfileProvider>();


            builder.AddSingleton <IConfiguration>(config);
            builder.AddCaching(config);

            // These registrations of the functions themselves are just for the DebugQueue. Ideally we don't want these registered in production
            if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
            {
                builder.AddScoped <OnCalcsGenerateAllocationResults>();
                builder.AddScoped <OnCalculationGenerateFailure>();
            }

            builder.AddScoped <ICalculationEngineService, CalculationEngineService>();
            builder.AddScoped <ICalculationEngine, CalculationEngine>();
            builder.AddScoped <IAllocationFactory, AllocationFactory>();
            builder.AddScoped <IDeadletterService, DeadletterService>();
            builder.AddScoped <IJobManagement, JobManagement>();
            builder.AddSingleton <IProviderSourceDatasetVersionKeyProvider, ProviderSourceDatasetVersionKeyProvider>();
            builder.AddSingleton <IFileSystemAccess, FileSystemAccess>();

            builder.AddSingleton <IAssemblyService, AssemblyService>();
            builder.AddSingleton <ICalculationAggregationService, CalculationAggregationService>();
            builder.AddScoped <ICalculationEnginePreviewService, CalculationEnginePreviewService>();

            builder.AddSingleton <IFileSystemCacheSettings, FileSystemCacheSettings>();
            builder.AddSingleton <IFileSystemCache, FileSystemCache>();

            builder.AddSingleton <IProviderSourceDatasetsRepository, ProviderSourceDatasetsRepository>((ctx) =>
            {
                CosmosDbSettings providerSourceDatasetsCosmosSettings = new CosmosDbSettings();

                config.Bind("CosmosDbSettings", providerSourceDatasetsCosmosSettings);

                providerSourceDatasetsCosmosSettings.ContainerName = "providerdatasets";

                CosmosRepository calcsCosmosRepository = new CosmosRepository(providerSourceDatasetsCosmosSettings, new CosmosClientOptions()
                {
                    ConnectionMode = ConnectionMode.Direct,
                    RequestTimeout = new TimeSpan(0, 0, 15),
                    MaxRequestsPerTcpConnection  = 8,
                    MaxTcpConnectionsPerEndpoint = 4,
                    ConsistencyLevel             = ConsistencyLevel.Eventual,
                    AllowBulkExecution           = true,
                    // MaxRetryAttemptsOnRateLimitedRequests = 1,
                    // MaxRetryWaitTimeOnRateLimitedRequests = new TimeSpan(0, 0, 30),
                });

                ICalculatorResiliencePolicies calculatorResiliencePolicies = ctx.GetService <ICalculatorResiliencePolicies>();

                return(new ProviderSourceDatasetsRepository(calcsCosmosRepository, calculatorResiliencePolicies));
            });

            builder.AddSingleton <IProviderResultCalculationsHashProvider, ProviderResultCalculationsHashProvider>();

            builder.AddSingleton <IProviderResultsRepository, ProviderResultsRepository>((ctx) =>
            {
                CosmosDbSettings calcResultsDbSettings = new CosmosDbSettings();

                config.Bind("CosmosDbSettings", calcResultsDbSettings);

                calcResultsDbSettings.ContainerName = "calculationresults";

                CosmosRepository calcsCosmosRepostory = new CosmosRepository(calcResultsDbSettings, new CosmosClientOptions()
                {
                    ConnectionMode = ConnectionMode.Direct,
                    RequestTimeout = new TimeSpan(0, 0, 15),
                    MaxRequestsPerTcpConnection  = 8,
                    MaxTcpConnectionsPerEndpoint = 2,
                    // MaxRetryWaitTimeOnRateLimitedRequests = new TimeSpan(0, 0, 30),
                    AllowBulkExecution = true,
                });

                ILogger logger = ctx.GetService <ILogger>();

                IProviderResultCalculationsHashProvider calculationsHashProvider = ctx.GetService <IProviderResultCalculationsHashProvider>();

                ICalculatorResiliencePolicies calculatorResiliencePolicies = ctx.GetService <ICalculatorResiliencePolicies>();

                IResultsApiClient resultsApiClient = ctx.GetService <IResultsApiClient>();

                IJobManagement jobManagement = ctx.GetService <IJobManagement>();

                return(new ProviderResultsRepository(
                           calcsCosmosRepostory,
                           logger,
                           calculationsHashProvider,
                           calculatorResiliencePolicies,
                           resultsApiClient,
                           jobManagement));
            });

            builder.AddSingleton <ISourceFileRepository, SourceFileRepository>((ctx) =>
            {
                BlobStorageOptions blobStorageOptions = new BlobStorageOptions();

                config.Bind("AzureStorageSettings", blobStorageOptions);

                blobStorageOptions.ContainerName = "source";

                IBlobContainerRepository blobContainerRepository = new BlobContainerRepository(blobStorageOptions);
                return(new SourceFileRepository(blobContainerRepository));
            });

            builder
            .AddSingleton <Services.CalcEngine.Interfaces.ICalculationsRepository, Services.CalcEngine.CalculationsRepository>();

            builder
            .AddSingleton <IDatasetAggregationsRepository, DatasetAggregationsRepository>();

            builder
            .AddSingleton <ICancellationTokenProvider, InactiveCancellationTokenProvider>();

            builder
            .AddSingleton <ISourceCodeService, SourceCodeService>();

            MapperConfiguration calculationsConfig = new MapperConfiguration(c =>
            {
                c.AddProfile <CalculationsMappingProfile>();
                c.AddProfile <CalcEngineMappingProfile>();
            });

            builder
            .AddSingleton(calculationsConfig.CreateMapper());

            builder.AddScoped <IUserProfileProvider, UserProfileProvider>();

            builder.AddCalculationsInterServiceClient(config, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddSpecificationsInterServiceClient(config, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddJobsInterServiceClient(config, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddPoliciesInterServiceClient(config, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddResultsInterServiceClient(config, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddDatasetsInterServiceClient(config, handlerLifetime: Timeout.InfiniteTimeSpan);

            builder.AddEngineSettings(config);

            builder.AddServiceBus(config, "calcengine");

            builder.AddCaching(config);

            builder.AddApplicationInsightsTelemetryClient(config, "CalculateFunding.Functions.CalcEngine");
            builder.AddApplicationInsightsServiceName(config, "CalculateFunding.Functions.CalcEngine");

            builder.AddLogging("CalculateFunding.Functions.CalcEngine", config);

            builder.AddTelemetry();

            builder.AddSearch(config);
            builder
            .AddSingleton <ISearchRepository <ProviderCalculationResultsIndex>, SearchRepository <ProviderCalculationResultsIndex> >();

            builder.AddFeatureToggling(config);

            PolicySettings policySettings = ServiceCollectionExtensions.GetPolicySettings(config);
            CalculatorResiliencePolicies calcResiliencePolicies = CreateResiliencePolicies(policySettings);

            builder.AddSingleton <ICalculatorResiliencePolicies>(calcResiliencePolicies);
            builder.AddSingleton <IJobManagementResiliencePolicies>((ctx) => new JobManagementResiliencePolicies()
            {
                JobsApiClient = calcResiliencePolicies.JobsApiClient
            });

            builder.AddSingleton <IValidator <ICalculatorResiliencePolicies>, CalculatorResiliencePoliciesValidator>();
            builder.AddSingleton <ICalculationEngineServiceValidator, CalculationEngineServiceValidator>();
            builder.AddSingleton <ISpecificationAssemblyProvider, SpecificationAssemblyProvider>();
            builder.AddSingleton <IBlobClient>(ctx =>
            {
                BlobStorageOptions options = new BlobStorageOptions();

                config.Bind("AzureStorageSettings", options);

                options.ContainerName = "source";

                IBlobContainerRepository blobContainerRepository = new BlobContainerRepository(options);
                return(new BlobClient(blobContainerRepository));
            });

            ServicePointManager.DefaultConnectionLimit = 200;

            return(builder.BuildServiceProvider());
        }
        public CalculationEngineService(
            ILogger logger,
            ICalculationEngine calculationEngine,
            ICacheProvider cacheProvider,
            IMessengerService messengerService,
            IProviderSourceDatasetsRepository providerSourceDatasetsRepository,
            ITelemetry telemetry,
            IProviderResultsRepository providerResultsRepository,
            ICalculationsRepository calculationsRepository,
            EngineSettings engineSettings,
            ICalculatorResiliencePolicies resiliencePolicies,
            IJobManagement jobManagement,
            ISpecificationsApiClient specificationsApiClient,
            IResultsApiClient resultsApiClient,
            IValidator <ICalculatorResiliencePolicies> calculatorResiliencePoliciesValidator,
            ICalculationEngineServiceValidator calculationEngineServiceValidator,
            ICalculationAggregationService calculationAggregationService,
            IAssemblyService assemblyService) : base(jobManagement, logger)
        {
            Guard.ArgumentNotNull(logger, nameof(logger));
            Guard.ArgumentNotNull(calculationEngine, nameof(calculationEngine));
            Guard.ArgumentNotNull(cacheProvider, nameof(cacheProvider));
            Guard.ArgumentNotNull(messengerService, nameof(messengerService));
            Guard.ArgumentNotNull(providerSourceDatasetsRepository, nameof(providerSourceDatasetsRepository));
            Guard.ArgumentNotNull(telemetry, nameof(telemetry));
            Guard.ArgumentNotNull(providerResultsRepository, nameof(providerResultsRepository));
            Guard.ArgumentNotNull(calculationsRepository, nameof(calculationsRepository));
            Guard.ArgumentNotNull(engineSettings, nameof(engineSettings));
            Guard.ArgumentNotNull(resiliencePolicies?.SpecificationsApiClient, nameof(resiliencePolicies.SpecificationsApiClient));
            Guard.ArgumentNotNull(resiliencePolicies?.CacheProvider, nameof(resiliencePolicies.CacheProvider));
            Guard.ArgumentNotNull(resiliencePolicies?.Messenger, nameof(resiliencePolicies.Messenger));
            Guard.ArgumentNotNull(resiliencePolicies?.ProviderSourceDatasetsRepository, nameof(resiliencePolicies.ProviderSourceDatasetsRepository));
            Guard.ArgumentNotNull(resiliencePolicies?.CalculationResultsRepository, nameof(resiliencePolicies.CalculationResultsRepository));
            Guard.ArgumentNotNull(resiliencePolicies?.CalculationsApiClient, nameof(resiliencePolicies.CalculationsApiClient));
            Guard.ArgumentNotNull(resiliencePolicies?.ResultsApiClient, nameof(resiliencePolicies.ResultsApiClient));
            Guard.ArgumentNotNull(specificationsApiClient, nameof(specificationsApiClient));
            Guard.ArgumentNotNull(calculatorResiliencePoliciesValidator, nameof(calculatorResiliencePoliciesValidator));
            Guard.ArgumentNotNull(calculationEngineServiceValidator, nameof(calculationEngineServiceValidator));
            Guard.ArgumentNotNull(resultsApiClient, nameof(resultsApiClient));
            Guard.ArgumentNotNull(calculationAggregationService, nameof(calculationAggregationService));
            Guard.ArgumentNotNull(assemblyService, nameof(assemblyService));

            _calculationEngineServiceValidator = calculationEngineServiceValidator;
            _logger            = logger;
            _calculationEngine = calculationEngine;
            _cacheProvider     = cacheProvider;
            _messengerService  = messengerService;
            _providerSourceDatasetsRepository = providerSourceDatasetsRepository;
            _telemetry = telemetry;
            _providerResultsRepository = providerResultsRepository;
            _calculationsRepository    = calculationsRepository;
            _engineSettings            = engineSettings;
            _cacheProviderPolicy       = resiliencePolicies.CacheProvider;
            _messengerServicePolicy    = resiliencePolicies.Messenger;
            _providerSourceDatasetsRepositoryPolicy = resiliencePolicies.ProviderSourceDatasetsRepository;
            _providerResultsRepositoryPolicy        = resiliencePolicies.CalculationResultsRepository;
            _calculationsApiClientPolicy            = resiliencePolicies.CalculationsApiClient;
            _specificationsApiClient       = specificationsApiClient;
            _specificationsApiPolicy       = resiliencePolicies.SpecificationsApiClient;
            _resultsApiClientPolicy        = resiliencePolicies.ResultsApiClient;
            _resultsApiClient              = resultsApiClient;
            _calculationAggregationService = calculationAggregationService;
            _assemblyService = assemblyService;

            _typeIdentifierGenerator = new VisualBasicTypeIdentifierGenerator();
        }
        public void RegisterComponents(IServiceCollection builder)
        {
            builder.AddScoped <ICalculationEngineService, CalculationEngineService>();
            builder.AddScoped <ICalculationEngine, CalculationEngine>();
            builder.AddScoped <IAllocationFactory, AllocationFactory>();
            builder.AddScoped <IJobManagement, JobManagement>();
            builder.AddSingleton <IProviderSourceDatasetVersionKeyProvider, ProviderSourceDatasetVersionKeyProvider>();
            builder.AddSingleton <IFileSystemAccess, FileSystemAccess>();

            builder.AddSingleton <IAssemblyService, AssemblyService>();
            builder.AddSingleton <ICalculationAggregationService, CalculationAggregationService>();
            builder.AddScoped <ICalculationEnginePreviewService, CalculationEnginePreviewService>();

            builder.AddSingleton <IFileSystemCacheSettings, FileSystemCacheSettings>();
            builder.AddSingleton <IFileSystemCache, FileSystemCache>();

            builder.AddSingleton <IProviderSourceDatasetsRepository, ProviderSourceDatasetsRepository>((ctx) =>
            {
                CosmosDbSettings providerSourceDatasetsCosmosSettings = new CosmosDbSettings();

                Configuration.Bind("CosmosDbSettings", providerSourceDatasetsCosmosSettings);

                providerSourceDatasetsCosmosSettings.ContainerName = "providerdatasets";

                CosmosRepository calcsCosmosRepository = new CosmosRepository(providerSourceDatasetsCosmosSettings, new CosmosClientOptions()
                {
                    ConnectionMode = ConnectionMode.Direct,
                    RequestTimeout = new TimeSpan(0, 0, 15),
                    MaxRequestsPerTcpConnection  = 8,
                    MaxTcpConnectionsPerEndpoint = 4,
                    ConsistencyLevel             = ConsistencyLevel.Eventual,
                    AllowBulkExecution           = true,
                });

                ICalculatorResiliencePolicies calculatorResiliencePolicies = ctx.GetService <ICalculatorResiliencePolicies>();

                return(new ProviderSourceDatasetsRepository(calcsCosmosRepository, calculatorResiliencePolicies));
            });

            builder.AddSingleton <IProviderResultCalculationsHashProvider, ProviderResultCalculationsHashProvider>();

            builder.AddSingleton <IProviderResultsRepository, ProviderResultsRepository>((ctx) =>
            {
                CosmosDbSettings calcResultsDbSettings = new CosmosDbSettings();

                Configuration.Bind("CosmosDbSettings", calcResultsDbSettings);

                calcResultsDbSettings.ContainerName = "calculationresults";

                CosmosRepository calcsCosmosRepostory = new CosmosRepository(calcResultsDbSettings, new CosmosClientOptions()
                {
                    ConnectionMode = ConnectionMode.Direct,
                    RequestTimeout = new TimeSpan(0, 0, 15),
                    MaxRequestsPerTcpConnection  = 8,
                    MaxTcpConnectionsPerEndpoint = 2,
                    // MaxRetryWaitTimeOnRateLimitedRequests = new TimeSpan(0, 0, 30),
                    AllowBulkExecution = true,
                });

                ILogger logger = ctx.GetService <ILogger>();

                IProviderResultCalculationsHashProvider calculationsHashProvider = ctx.GetService <IProviderResultCalculationsHashProvider>();

                ICalculatorResiliencePolicies calculatorResiliencePolicies = ctx.GetService <ICalculatorResiliencePolicies>();

                IResultsApiClient resultsApiClient = ctx.GetService <IResultsApiClient>();

                IJobManagement jobManagement = ctx.GetService <IJobManagement>();

                return(new ProviderResultsRepository(
                           calcsCosmosRepostory,
                           logger,
                           calculationsHashProvider,
                           calculatorResiliencePolicies,
                           resultsApiClient,
                           jobManagement));
            });

            builder
            .AddSingleton <IBlobContainerRepository, BlobContainerRepository>();

            builder
            .AddSingleton <ICalculationsRepository, CalculationsRepository>();

            builder
            .AddSingleton <IDatasetAggregationsRepository, DatasetAggregationsRepository>();

            builder
            .AddSingleton <ICancellationTokenProvider, InactiveCancellationTokenProvider>();

            MapperConfiguration calculationsConfig = new MapperConfiguration(c =>
            {
                c.AddProfile <CalculationsMappingProfile>();
                c.AddProfile <CalcEngineMappingProfile>();
            });

            builder
            .AddSingleton(calculationsConfig.CreateMapper());

            builder.AddSingleton <IUserProfileProvider, UserProfileProvider>();

            builder.AddCalculationsInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddSpecificationsInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddJobsInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddPoliciesInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddResultsInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddDatasetsInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);
            builder.AddProvidersInterServiceClient(Configuration, handlerLifetime: Timeout.InfiniteTimeSpan);

            builder.AddEngineSettings(Configuration);

            builder.AddServiceBus(Configuration, "calcengine");

            builder.AddCaching(Configuration);

            builder.AddApplicationInsightsTelemetry();
            builder.AddApplicationInsightsTelemetryClient(Configuration, "CalculateFunding.Api.CalcEngine");
            builder.AddApplicationInsightsServiceName(Configuration, "CalculateFunding.Api.CalcEngine");

            builder.AddLogging("CalculateFunding.Api.CalcEngine");

            builder.AddTelemetry();

            builder.AddSearch(Configuration);
            builder
            .AddSingleton <ISearchRepository <ProviderCalculationResultsIndex>, SearchRepository <ProviderCalculationResultsIndex> >();

            builder.AddFeatureToggling(Configuration);

            PolicySettings policySettings = ServiceCollectionExtensions.GetPolicySettings(Configuration);
            CalculatorResiliencePolicies calcResiliencePolicies = CreateResiliencePolicies(policySettings);

            builder.AddSingleton <ICalculatorResiliencePolicies>(calcResiliencePolicies);
            builder.AddSingleton <IJobManagementResiliencePolicies>((ctx) => new JobManagementResiliencePolicies()
            {
                JobsApiClient = calcResiliencePolicies.JobsApiClient
            });

            builder.AddSingleton <IValidator <ICalculatorResiliencePolicies>, CalculatorResiliencePoliciesValidator>();
            builder.AddSingleton <ICalculationEngineServiceValidator, CalculationEngineServiceValidator>();
            builder.AddSingleton <ISpecificationAssemblyProvider, SpecificationAssemblyProvider>();
            builder.AddSingleton <IBlobClient>(ctx =>
            {
                BlobStorageOptions options = new BlobStorageOptions();

                Configuration.Bind("AzureStorageSettings", options);

                options.ContainerName = "source";

                IBlobContainerRepository blobContainerRepository = new BlobContainerRepository(options);
                return(new BlobClient(blobContainerRepository));
            });

            builder.AddApiKeyMiddlewareSettings((IConfigurationRoot)Configuration);

            builder.AddHttpContextAccessor();

            builder.AddHealthCheckMiddleware();

            if (Configuration.IsSwaggerEnabled())
            {
                builder.ConfigureSwaggerServices(title: "CalcEngine Microservice API", version: "v1");
            }
        }