private async Task <(IEnumerable <CalculationAggregation>, long)> BuildAggregations(GenerateAllocationMessageProperties messageProperties) { Stopwatch sw = Stopwatch.StartNew(); BuildAggregationRequest aggreagationRequest = new BuildAggregationRequest { BatchCount = messageProperties.BatchCount, GenerateCalculationAggregationsOnly = messageProperties.GenerateCalculationAggregationsOnly, SpecificationId = messageProperties.SpecificationId }; IEnumerable <CalculationAggregation> aggregations = await _calculationAggregationService.BuildAggregations(aggreagationRequest); return(aggregations, sw.ElapsedMilliseconds); }
public async Task <IEnumerable <CalculationAggregation> > BuildAggregations(BuildAggregationRequest aggreagationRequest) { IEnumerable <CalculationAggregation> aggregations = Enumerable.Empty <CalculationAggregation>(); aggregations = await _cacheProvider.GetAsync <List <CalculationAggregation> >( $"{ CacheKeys.DatasetAggregationsForSpecification}{aggreagationRequest.SpecificationId}"); if (DoesNotExistInCache(aggregations)) { aggregations = (await _datasetAggregationsRepository.GetDatasetAggregationsForSpecificationId(aggreagationRequest.SpecificationId)).Select(m => new CalculationAggregation { SpecificationId = m.SpecificationId, Values = m.Fields.IsNullOrEmpty() ? Enumerable.Empty <AggregateValue>() : m.Fields.Select(f => new AggregateValue { AggregatedType = f.FieldType, FieldDefinitionName = f.FieldDefinitionName, Value = f.Value }) }); await _cacheProvider.SetAsync($"{CacheKeys.DatasetAggregationsForSpecification}{aggreagationRequest.SpecificationId}", aggregations.ToList()); } if (!aggreagationRequest.GenerateCalculationAggregationsOnly) { ConcurrentDictionary <string, List <decimal> > cachedCalculationAggregations = new ConcurrentDictionary <string, List <decimal> >( StringComparer.InvariantCultureIgnoreCase); List <Task> allTasks = new List <Task>(); SemaphoreSlim throttler = new SemaphoreSlim(_engineSettings.CalculationAggregationRetreivalParallelism); for (int i = 1; i <= aggreagationRequest.BatchCount; i++) { await throttler.WaitAsync(); int currentBatchNumber = i; allTasks.Add( Task.Run(async() => { try { string batchedCacheKey = $"{CacheKeys.CalculationAggregations}{aggreagationRequest.SpecificationId}_{currentBatchNumber}"; Dictionary <string, List <decimal> > cachedCalculationAggregationsPart = await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.GetAsync <Dictionary <string, List <decimal> > >(batchedCacheKey)); if (!cachedCalculationAggregationsPart.IsNullOrEmpty()) { foreach (KeyValuePair <string, List <decimal> > cachedAggregations in cachedCalculationAggregationsPart) { List <decimal> values = cachedCalculationAggregations.GetOrAdd(cachedAggregations.Key, new List <decimal>()); values.AddRange(cachedAggregations.Value); } } } finally { throttler.Release(); } })); } await TaskHelper.WhenAllAndThrow(allTasks.ToArray()); if (!cachedCalculationAggregations.IsNullOrEmpty()) { foreach (KeyValuePair <string, List <decimal> > cachedCalculationAggregation in cachedCalculationAggregations.OrderBy(o => o.Key)) { aggregations = aggregations.Concat(new[] { new CalculationAggregation { SpecificationId = aggreagationRequest.SpecificationId, Values = new [] { new AggregateValue { FieldDefinitionName = cachedCalculationAggregation.Key, AggregatedType = AggregatedType.Sum, Value = cachedCalculationAggregation.Value.Sum() }, new AggregateValue { FieldDefinitionName = cachedCalculationAggregation.Key, AggregatedType = AggregatedType.Min, Value = cachedCalculationAggregation.Value.Min() }, new AggregateValue { FieldDefinitionName = cachedCalculationAggregation.Key, AggregatedType = AggregatedType.Max, Value = cachedCalculationAggregation.Value.Max() }, new AggregateValue { FieldDefinitionName = cachedCalculationAggregation.Key, AggregatedType = AggregatedType.Average, Value = cachedCalculationAggregation.Value.Average() }, } } }); } } } return(aggregations); }
public async Task <IActionResult> PreviewCalculationResult( string specificationId, string providerId, PreviewCalculationRequest previewCalculationRequest) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); Guard.IsNullOrWhiteSpace(providerId, nameof(providerId)); Guard.ArgumentNotNull(previewCalculationRequest, nameof(previewCalculationRequest)); Assembly assembly = Assembly.Load(previewCalculationRequest.AssemblyContent); IAllocationModel allocationModel = _calculationEngine.GenerateAllocationModel(assembly); SpecificationSummary specificationSummary = await GetSpecificationSummary(specificationId); ApiResponse <ProviderVersionSearchResult> providerVersionSearchResultApiResponse = await _providersApiClientPolicy.ExecuteAsync(() => _providersApiClient.GetProviderByIdFromProviderVersion( specificationSummary.ProviderVersionId, providerId)); ProviderVersionSearchResult providerVersionSearchResult = providerVersionSearchResultApiResponse.Content; if (providerVersionSearchResult == null) { return(new NotFoundResult()); } ProviderSummary providerSummary = _mapper.Map <ProviderSummary>(providerVersionSearchResult); List <CalculationSummaryModel> calculationSummaries = new List <CalculationSummaryModel>(); IEnumerable <CalculationSummaryModel> specCalculationSummaries = await GetCalculationSummaries(specificationId); calculationSummaries.AddRange(specCalculationSummaries); calculationSummaries.Add(previewCalculationRequest.PreviewCalculationSummaryModel); Dictionary <string, Dictionary <string, ProviderSourceDataset> > providerSourceDatasets = await _providerSourceDatasetsRepository.GetProviderSourceDatasetsByProviderIdsAndRelationshipIds( specificationId, new[] { providerId }, specificationSummary.DataDefinitionRelationshipIds); Dictionary <string, ProviderSourceDataset> providerSourceDataset = providerSourceDatasets[providerId]; BuildAggregationRequest buildAggregationRequest = new BuildAggregationRequest { SpecificationId = specificationId, GenerateCalculationAggregationsOnly = true, BatchCount = 100 }; IEnumerable <CalculationAggregation> calculationAggregations = await _calculationAggregationService.BuildAggregations(buildAggregationRequest); ProviderResult providerResult = _calculationEngine.CalculateProviderResults( allocationModel, specificationId, calculationSummaries, providerSummary, providerSourceDataset, calculationAggregations ); return(new OkObjectResult(providerResult)); }