private async Task InvokePipelineAsync(IWorkProvider provider, WorkItem item) { using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token)) { var progress = new QuidjiboProgress(); progress.ProgressChanged += async(sender, tracker) => { var progressProvider = await _progressProviderFactory.CreateAsync(item.Queue, _cts.Token); var progressItem = new ProgressItem { Id = Guid.NewGuid(), CorrelationId = item.CorrelationId, RecordedOn = DateTime.UtcNow, Name = item.Name, Queue = item.Queue, Note = tracker.Text, Value = tracker.Value, WorkId = item.Id }; await progressProvider.ReportAsync(progressItem, _cts.Token); }; var renewTask = RenewAsync(provider, item, linkedTokenSource.Token); var context = new QuidjiboContext { Item = item, WorkProvider = provider, Progress = progress, State = new PipelineState() }; try { await _quidjiboPipeline.StartAsync(context, linkedTokenSource.Token); if (context.State.Success) { await provider.CompleteAsync(item, linkedTokenSource.Token); _logger.LogDebug("Completed : {0}", item.Id); } else { await provider.FaultAsync(item, linkedTokenSource.Token); _logger.LogError("Faulted : {0}", item.Id); } } catch (Exception exception) { _logger.LogError("Faulted : {0}, {1}", item.Id, exception); await provider.FaultAsync(item, linkedTokenSource.Token); } finally { _logger.LogDebug("Release : {0}", item.Id); linkedTokenSource.Cancel(); await renewTask; await _quidjiboPipeline.EndAsync(context); } } }
public async Task WorkLoopAsyncTest(int throttle, bool singleLoop) { // Arrange var testQueue = new ConcurrentQueue <WorkItem>(); var completedWork = new ConcurrentBag <WorkItem>(); var defaultItems = GenFu.GenFu.ListOf <WorkItem>(); defaultItems.ForEach(x => { x.Queue = "default"; testQueue.Enqueue(x); }); var primaryItems = GenFu.GenFu.ListOf <WorkItem>(); primaryItems.ForEach(x => { x.Queue = "primary"; testQueue.Enqueue(x); }); var secondaryItems = GenFu.GenFu.ListOf <WorkItem>(); secondaryItems.ForEach(x => { x.Queue = "secondary"; testQueue.Enqueue(x); }); _quidjiboConfiguration.EnableWorker.Returns(true); _quidjiboConfiguration.Throttle.Returns(throttle); _quidjiboConfiguration.LockInterval.Returns(60); _quidjiboConfiguration.SingleLoop.Returns(singleLoop); _quidjiboConfiguration.Queues.Returns(new[] { "default", "primary", "secondary" }); _workProvider.ReceiveAsync(Arg.Any <string>(), Arg.Any <CancellationToken>()) .Returns(x => testQueue.TryDequeue(out var item) ? Task.FromResult(new List <WorkItem> { item }) : Task.FromResult(new List <WorkItem>(0))); _workProvider.RenewAsync(Arg.Any <WorkItem>(), Arg.Any <CancellationToken>()).Returns(Task.FromResult(DateTime.UtcNow.AddMinutes(1))); _workProvider.CompleteAsync(Arg.Any <WorkItem>(), Arg.Any <CancellationToken>()) .Returns(x => { completedWork.Add(x.Arg <WorkItem>()); return(Task.CompletedTask); }); // Act _sut.Start(); // Assert while (!testQueue.IsEmpty && !_cts.IsCancellationRequested) { } testQueue.Count.Should().Be(0); if (singleLoop) { await _workProviderFactory.Received(1).CreateAsync(Arg.Any <string>(), Arg.Any <CancellationToken>()); } else { await _workProviderFactory.Received(1).CreateAsync(Arg.Is <string>(x => x == "default"), Arg.Any <CancellationToken>()); await _workProviderFactory.Received(1).CreateAsync(Arg.Is <string>(x => x == "primary"), Arg.Any <CancellationToken>()); await _workProviderFactory.Received(1).CreateAsync(Arg.Is <string>(x => x == "secondary"), Arg.Any <CancellationToken>()); } await _pipeline.ReceivedWithAnyArgs(75).StartAsync(Arg.Any <IQuidjiboContext>(), Arg.Any <CancellationToken>()); }