public async Task Recipients_are_canceled_after_timeout() { var collection = new RecipientsCollection(); collection.Add <SomeType>(); collection.Add <SomeCancellableType>(); collection.Add(new SomeAlmostNeverEndingType()); collection.Add((int n) => n.ToString()); collection.Add(async(int n, CancellationToken token) => { using var cancellation = new CancellationTokenTaskSource <bool>(token); await CatchCancellation(cancellation.Task); return(n.ToString()); }); var aggregator = new Aggregator(collection) { CancellationWindow = TimeSpan.FromSeconds(2) }; { var response = await aggregator.Send(42, TimeSpan.FromSeconds(2)); Assert.Equal(collection.RecipientsCount, response.Completed.Count); Assert.Empty(response.Incomplete); } { var response = await aggregator.Send <string>(42, TimeSpan.FromSeconds(2)); Assert.Equal(collection.RecipientsCount, response.Completed.Count); Assert.Empty(response.Incomplete); } }
private async Task <IReadOnlyList <RecipientRunner <object?> > > Invoke( IReadOnlyList <Recipient> recipients, object request, CancellationToken cancellationToken) { var runners = recipients.SelectMany(recipient => recipient.Accept(request, cancellationToken)).ToArray(); var tasks = runners .Select(runner => runner.Start()) .ToArray(); var allTasksCompleted = Task.WhenAll(tasks); using var cancellation = new CancellationTokenTaskSource <object?[]>(cancellationToken); await Task.WhenAny(allTasksCompleted, cancellation.Task).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { await WaitForLatecomers(runners).ConfigureAwait(false); } return(runners); }