public async Task BatchBlockKeepsPostponedMessages()
        {
            BatchBlock <int> bb = new BatchBlock <int>(batchSize: 2,
                                                       dataflowBlockOptions: new GroupingDataflowBlockOptions()
            {
                BoundedCapacity = 3
            });

            TestTargetBlock <int[]> testTarget = new TestTargetBlock <int[]>();

            testTarget.ConsumptionMode = DataflowMessageStatus.Postponed;
            bb.LinkTo(testTarget, PropagateCompletion);

            // Assumption: if the target of the BatchBlock is postponing messages,
            // BatchBlock will accept incoming messages until it runs out of capacity.
            Assert.True(bb.Post(1));
            Assert.True(bb.Post(2));

            // Still able to accept one more message
            Assert.True(bb.Post(3));

            // Out of capacity.
            Assert.False(bb.Post(4));

            // Send() a message to give the block a chance to postpone it
            bb.SendAsync(5).Forget();

            // First batch offered, but postponed
            bool gotFirstBatch = await TaskUtils.PollWaitAsync(() => testTarget.MessagesPostponed.Count == 1, MessageArrivalTimeout);

            Assert.True(gotFirstBatch);

            // Assumption: once the BatchBlock target stops postponing, BatchBlock will keep pushing data to target
            // until it runs out of buffered messages.
            testTarget.ConsumptionMode = DataflowMessageStatus.Accepted;
            testTarget.ConsumePostponedMessages();

            // The second, postponed message should allow the block to complete two batches
            bool gotTwoBatches = await TaskUtils.PollWaitAsync(() => testTarget.MessagesConsumed.Count == 2, MessageArrivalTimeout);

            Assert.True(gotTwoBatches);
            Assert.True(testTarget.MessagesConsumed.All((m) => m.Length == 2));
        }
        private async Task BlockKeepsPostponedMessages(Func <ISourceBlock <int> > BlockFactory)
        {
            // This test requires longer timeout than most of the other tests in this suite, otherwise it occasionally fails on slower machines
            // If it fails nevertheless, switch to custom TaskScheduler.
            TimeSpan longArrivalTimeout = TimeSpan.FromMilliseconds(MessageArrivalTimeout.TotalMilliseconds * 10.0);

            ISourceBlock <int> block  = BlockFactory();
            ITargetBlock <int> blockT = (ITargetBlock <int>)block;

            TestTargetBlock <int> testTarget = new TestTargetBlock <int>();

            testTarget.ConsumptionMode = DataflowMessageStatus.Postponed;
            block.LinkTo(testTarget, PropagateCompletion);

            // Assumption: if the target of the block is postponing messages,
            // The block will accept incoming messages until it runs out of capacity.
            Assert.True(blockT.Post(1));
            Assert.True(blockT.Post(2));
            Assert.True(blockT.Post(3));

            // Out of capacity
            Assert.False(blockT.Post(4));

            // However SendAsync() will allow postponing the message, so the message will be eventually delivered
            blockT.SendAsync(5).Forget();

            // Wait till the block offers a message
            // Assumption: only one message will be offered, the block will not offer more messages if the target postpones
            bool messageOffered = await TaskUtils.PollWaitAsync(() => testTarget.MessagesPostponed.Count == 1, longArrivalTimeout);

            Assert.True(messageOffered);

            // Assumption: once the block target stops postponing, the block will keep pushing data to target
            // until it runs out of buffered messages.
            testTarget.ConsumptionMode = DataflowMessageStatus.Accepted;
            testTarget.ConsumePostponedMessages();
            bool gotAllMessages = await TaskUtils.PollWaitAsync(() => testTarget.MessagesConsumed.Count == 4, longArrivalTimeout);

            Assert.True(gotAllMessages, "We should have gotten 4 messages");
            Assert.Equal(testTarget.MessagesConsumed.OrderBy((i) => i), new int[] { 1, 2, 3, 5 });
        }
        public async Task BroadcastBlockDoesNotRememberMoreThanOnePostponedMessage()
        {
            BroadcastBlock <int> bb = new BroadcastBlock <int>((i) => i,
                                                               new DataflowBlockOptions
            {
                BoundedCapacity = 3
            });

            TestTargetBlock <int> target = new TestTargetBlock <int>();

            target.ConsumptionMode = DataflowMessageStatus.Postponed;
            bb.LinkTo(target, PropagateCompletion);

            bb.Post(1);
            bb.Post(2);
            await TaskUtils.PollWaitAsync(() => target.MessagesPostponed.Count == 2, MessageArrivalTimeout);

            target.ConsumePostponedMessages();
            // Assumption: only one message (the last one) will be successfully consumed. The previous message was overwritten,
            // so when the target inquires about it, it is gone.
            Assert.Single(target.MessagesConsumed);
        }
Exemple #4
0
        private async Task BlockKeepsPostponedMessages(Func <ISourceBlock <int> > BlockFactory)
        {
            ISourceBlock <int> block  = BlockFactory();
            ITargetBlock <int> blockT = (ITargetBlock <int>)block;

            TestTargetBlock <int> testTarget = new TestTargetBlock <int>();

            testTarget.ConsumptionMode = DataflowMessageStatus.Postponed;
            block.LinkTo(testTarget, PropagateCompletion);

            // Assumption: if the target of the block is postponing messages,
            // The block will accept incoming messages until it runs out of capacity.
            Assert.True(blockT.Post(1));
            Assert.True(blockT.Post(2));
            Assert.True(blockT.Post(3));

            // Out of capacity
            Assert.False(blockT.Post(4));

            // However SendAsync() will allow postponing the message, sot the message will be eventually delivered
            blockT.SendAsync(5).Forget();

            // Wait till the block offers a message
            // Assumption: only one message will be offered, the block will not offer more messages if the target postpones
            bool messageOffered = await TaskUtils.PollWaitAsync(() => testTarget.MessagesPostponed.Count == 1, MessageArrivalTimeout);

            Assert.True(messageOffered);

            // Assumption: once the block target stops postponing, the block will keep pushing data to target
            // until it runs out of buffered messages.
            testTarget.ConsumptionMode = DataflowMessageStatus.Accepted;
            testTarget.ConsumePostponedMessages();
            // Use 10 times the normal message arrival timeout for extra padding--the test tended to be a bit flakey at this point.
            // If this happens again, switch to custom TaskScheduler.
            bool gotAllMessages = await TaskUtils.PollWaitAsync(() => testTarget.MessagesConsumed.Count == 4, TimeSpan.FromMilliseconds(MessageArrivalTimeout.TotalMilliseconds * 10));

            Assert.True(gotAllMessages, "We should have gotten 4 messages");
            Assert.Equal(testTarget.MessagesConsumed.OrderBy((i) => i), new int[] { 1, 2, 3, 5 });
        }