public static async Task <ListOfEntityResult <PartnerSdkModels.Customers.Customer> > GetCustomers( int page, int count, string continuationToken, bool includeCustomerDetails = true) { // Read customers in page and with received count // Max count is 500 PartnerSdkModels.SeekBasedResourceCollection <PartnerSdkModels.Customers.Customer> customers; if (string.IsNullOrWhiteSpace(continuationToken)) { customers = await _partnerOperations.Customers.QueryAsync( PartnerSdkModels.Query.QueryFactory.Instance.BuildIndexedQuery(count, page, token: continuationToken)); } else { // Use continuation token customers = await _partnerOperations.Customers.QueryAsync( PartnerSdkModels.Query.QueryFactory.Instance.BuildSeekQuery( PartnerSdkModels.Query.SeekOperation.Next, token: continuationToken)); } var result = new ListOfEntityResult <PartnerSdkModels.Customers.Customer>() { Items = customers.Items != null?customers.Items.ToList() : new List <PartnerSdkModels.Customers.Customer>(0), // The last page does not have a next link ContinuationToken = customers.Links != null && customers.Links.Next != null ? customers.ContinuationToken : string.Empty }; // Include Customer Details if (includeCustomerDetails) { // Load each customer details var tasks = result.Items.Select(async customer => await GetCustomerAsync(Guid.Parse(customer.Id))); result.Items = new List <PartnerSdkModels.Customers.Customer>(await Task.WhenAll(tasks)); } // Map to our domain return(result); }
private static async Task ExtractReportInformationWithProcessor() { ExceptionDispatchInfo capturedException = null; try { #region Output Channel initialization _logger.Info("Initializating ..."); _correlationId = await _reportProcessor.OutputToChannelInitializeAsync(); #endregion #region Extract report information // Process customers in batches ListOfEntityResult <PartnerSdkModels.Customers.Customer> customers = new ListOfEntityResult <PartnerSdkModels.Customers.Customer>(); int currentPage = 1; int totalProcessedCustomers = 0; do { _logger.Info("Current total of processed customers: " + totalProcessedCustomers); _logger.Info("Current elapsed time: " + FormatStopwatch()); _logger.Info("Get Batch of Customers: Page = " + currentPage + " Count = " + MAXIMUM_CUSTOMERS_PER_BATCH); // Get batch of customers customers = await GetCustomers(currentPage, MAXIMUM_CUSTOMERS_PER_BATCH, customers.ContinuationToken); totalProcessedCustomers += customers.Items.Count(); List <PartnerSdkModels.Customers.Customer> batchOfCustomers = customers.Items.ToList(); // Basic threading mechanism, for processing more than one customer at a time // A MAXIMUM_NUMBER_OF_TASKS will be used // The partition is to guarantee approximate execution order of customers Partitioner.Create(batchOfCustomers).AsParallel().AsOrdered() .WithDegreeOfParallelism(MAXIMUM_NUMBER_OF_TASKS).ForAll(customer => _reportProcessor.ReportItemProcessorFunctionAsync( _reportOutputItems, batchOfCustomers, customer, currentPage) .ConfigureAwait(false).GetAwaiter().GetResult()); // Fill items with correlation Id foreach (var item in _reportOutputItems) { item.CorrelationId = _correlationId; item.Timestamp = DateTime.UtcNow; } // Write this batch to output and clear outputted lines await _reportProcessor.OutputToChannelBatchAsync(_reportOutputItems); _reportOutputItems.Dispose(); _reportOutputItems = new BlockingCollection <ReportOutputItem>(); // Increase page currentPage++; } // Check if more customers available while (string.IsNullOrWhiteSpace(customers.ContinuationToken) == false); // Update end status with success await _reportProcessor.OutputToChannelSuccessAsync(); _logger.Info("Number of total processed customers: " + totalProcessedCustomers); } catch (Exception e) { capturedException = ExceptionDispatchInfo.Capture(e); } // Because await is not supported in catch block if (capturedException != null && _correlationId != null) { // Update end status with error await _reportProcessor.OutputToChannelErrorAsync(); capturedException.Throw(); } #endregion }