Example #1
0
        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);
            }
        }
Example #2
0
        public async Task Cancellation_window_is_applied_correctly()
        {
            var collection = new RecipientsCollection();

            collection.Add <SomeAlmostNeverEndingType>();
            collection.Add <SomeLongProcessingType>();

            var aggregator = new Aggregator(collection)
            {
                CancellationWindow = TimeSpan.FromSeconds(3)
            };

            {
                var response = await aggregator.Send(42, timeout : TimeSpan.FromSeconds(1));

                Assert.Equal(1, response.Completed.Count);
                Assert.Equal(1, response.Incomplete.Count);
            }

            {
                // Gives SomeLongProcessingType the time to complete
                // even though it doesn't accept a cancellation token.
                aggregator.AllowCancellationWindowOnAllRecipients = true;

                var response = await aggregator.Send(42, timeout : TimeSpan.FromSeconds(1));

                Assert.Equal(2, response.Completed.Count);
                Assert.Equal(0, response.Incomplete.Count);
            }
        }
        public async Task Responses_expose_the_recipient_name_and_type()
        {
            var collection = new RecipientsCollection();

            collection.Add((int n) => n.ToString(), name: "Some delegate");
            collection.Add(new SomeFaultingType(), name: "Some faulting type");
            collection.Add <SomeNeverEndingType>(name: "Some never ending type");

            var localAggregator = new Aggregator(collection);
            var result          = await localAggregator.Send <string>(42, timeout : TimeSpan.FromSeconds(1));

            Assert.NotNull(result);

            Assert.Equal(1, result.Completed.Count);
            Assert.Equal("Some delegate", result.Completed[0].Recipient.Name);
            Assert.Null(result.Completed[0].Recipient.Type);

            Assert.Equal(1, result.Faulted.Count);
            Assert.Equal("Some faulting type", result.Faulted[0].Recipient.Name);
            Assert.Equal(typeof(SomeFaultingType), result.Faulted[0].Recipient.Type);

            Assert.Equal(1, result.Incomplete.Count);
            Assert.Equal("Some never ending type", result.Incomplete[0].Recipient.Name);
            Assert.Equal(typeof(SomeNeverEndingType), result.Incomplete[0].Recipient.Type);
        }
        public async Task Colliding_recipients_use_all_methods_by_design()
        {
            var collection = new RecipientsCollection();

            collection.Add <SomeCollidingType>(CollisionStrategy.UseAllMethodsMatching);

            var collisionDetected = false;

            collection.OnCollision += _ => collisionDetected = true;

            var aggregator = new Aggregator(collection);

            var(completed, faulted, incomplete) = await aggregator.Send(42);

            Assert.Equal(2, completed.Count);
            Assert.Empty(faulted);
            Assert.Empty(incomplete);

            Assert.False(collisionDetected);

            var stringsOnly = await aggregator.Send <string>(42);

            Assert.Equal(2, stringsOnly.Completed.Count);
            Assert.Empty(stringsOnly.Faulted);
            Assert.Empty(stringsOnly.Incomplete);

            Assert.False(collisionDetected);
        }
        public async Task Recipients_comply_with_lifetime()
        {
            var transients = 0;
            var scoped     = 0;
            var singletons = 0;

            var collection = new RecipientsCollection();

            collection.Add(() => { transients++; return(new SomeType()); }, name: null, lifetime: Lifetime.Transient);
            collection.Add(() => { scoped++; return(new SomeOtherType()); }, name: null, lifetime: Lifetime.Scoped);
            collection.Add(() => { singletons++; return(new SomeAsyncType()); }, name: null, lifetime: Lifetime.Singleton);

            var aggregator        = new Aggregator(collection);
            var anotherAggregator = new Aggregator(collection);

            await aggregator.Send(42);

            Assert.Equal(1, transients);
            Assert.Equal(1, scoped);
            Assert.Equal(1, singletons);

            await anotherAggregator.Send(42);

            Assert.Equal(2, transients);
            Assert.Equal(2, scoped);
            Assert.Equal(1, singletons);

            await Task.WhenAll(aggregator.Send(42), anotherAggregator.Send(42));

            Assert.Equal(4, transients);
            Assert.Equal(2, scoped);
            Assert.Equal(1, singletons);
        }
        public AggregatorTests()
        {
            var collection = new RecipientsCollection();

            collection.Add <SomeType>();
            collection.Add <SomeAsyncType>();
            collection.Add <SomePossiblyAsyncType>();
            collection.Add <SomeCollidingType>();
            collection.Add <SomeFaultingType>();
            collection.Add <SomeNeverEndingType>();

            _aggregator = new Aggregator(collection);
        }
        public async Task Recipients_can_return_nullable()
        {
            var collection = new RecipientsCollection();

            collection.Add <SomeTypeReturningNullable>();

            var aggregator = new Aggregator(collection);

            var response = await aggregator.Send(42);

            Assert.NotNull(response);
            Assert.Single(response.Completed);
            Assert.Empty(response.Faulted);

            var completed = response.Completed[0];

            Assert.Equal(typeof(SomeTypeReturningNullable), completed.Recipient.Type);
            Assert.Null(completed.Result);
        }
        public async Task Colliding_recipients_are_ignored_by_design()
        {
            var collection = new RecipientsCollection();

            collection.Add <SomeCollidingType>(CollisionStrategy.IgnoreRecipient);

            var collisionDetected = false;

            collection.OnCollision += _ => collisionDetected = true;

            var aggregator = new Aggregator(collection);

            var(completed, faulted, incomplete) = await aggregator.Send(42);

            Assert.Empty(completed);
            Assert.Empty(faulted);
            Assert.Empty(incomplete);

            Assert.True(collisionDetected);
        }
 public Aggregator(RecipientsCollection collection)
 {
     _scope             = collection.CreateScope();
     CancellationWindow = TimeSpan.FromMilliseconds(100);
 }