public async Task Given_A_CategoryList_And_PageSize_Should_Invoke_Process_Method_3_Times() { // Arrange const int expected = 3; var categories = new List <string> { "category1", "category2", "category3" }; const int pageSize = 10; _articleCategoryDataSource .Producer(Arg.Any <string>(), Arg.Any <int>()) .Returns ( new List <UnexpandedArticle[]> { new UnexpandedArticle[0] }.ToAsyncEnumerable(), new List <UnexpandedArticle[]> { new UnexpandedArticle[0] }.ToAsyncEnumerable(), new List <UnexpandedArticle[]> { new UnexpandedArticle[0] }.ToAsyncEnumerable() ); _articleBatchProcessor.Process(Arg.Any <string>(), Arg.Any <UnexpandedArticle[]>()) .Returns(new ArticleBatchTaskResult()); // Act await _sut.Process(categories, pageSize); // Assert await _articleBatchProcessor.Received(expected).Process(Arg.Any <string>(), Arg.Any <UnexpandedArticle[]>()); }
public async Task <ArticleBatchTaskResult> Process(string category, int pageSize) { var response = new ArticleBatchTaskResult { Category = category }; await foreach (var unexpandedArticleBatch in _articleCategoryDataSource.Producer(category, pageSize)) { var articleBatchTaskResult = await _articleBatchProcessor.Process(category, unexpandedArticleBatch); response.Processed += articleBatchTaskResult.Processed; response.Failed.AddRange(articleBatchTaskResult.Failed); } return(response); }
public Task <ArticleBatchTaskResult> Process(string category, int pageSize) { var response = new ArticleBatchTaskResult { Category = category }; var processorCount = Environment.ProcessorCount; // Pipeline members var articleBatchBufferBlock = new BufferBlock <UnexpandedArticle[]>(); var articleTransformBlock = new TransformBlock <UnexpandedArticle[], ArticleBatchTaskResult>(articles => _articleBatchProcessor.Process(category, articles)); var articleActionBlock = new ActionBlock <ArticleBatchTaskResult>(delegate(ArticleBatchTaskResult result) { response.Processed += result.Processed; response.Failed.AddRange(result.Failed); }, // Specify a maximum degree of parallelism. new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = processorCount }); // Form the pipeline articleBatchBufferBlock.LinkTo(articleTransformBlock); articleTransformBlock.LinkTo(articleActionBlock); // Create the completion tasks: articleBatchBufferBlock.Completion .ContinueWith(t => { if (t.IsFaulted) { ((IDataflowBlock)articleTransformBlock).Fault(t.Exception); } else { articleTransformBlock.Complete(); } }); articleTransformBlock.Completion .ContinueWith(t => { if (t.IsFaulted) { ((IDataflowBlock)articleActionBlock).Fault(t.Exception); } else { articleActionBlock.Complete(); } }); // Process "Category" and generate article batch data _articleCategoryDataSource.Producer(category, pageSize, articleBatchBufferBlock); // Mark the head of the pipeline as complete. The continuation tasks // propagate completion through the pipeline as each part of the // pipeline finishes. articleActionBlock.Completion.Wait(); return(Task.FromResult(response)); }