示例#1
0
        public void Should_properly_handle_exception()
        {
            IPipe <ConsumeContext> pipe = Pipe.New <ConsumeContext>(x =>
            {
                x.UseTransaction();
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(async payload =>
                {
                    await Task.Yield();

                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);

                        scope.Complete();
                    }

                    throw new InvalidOperationException("This is a friendly boom");
                });
                x.UseExecute(payload => Console.WriteLine("After Transaction: {0}", Thread.CurrentThread.ManagedThreadId));
            });

            var context = new TestConsumeContext <PingMessage>(new PingMessage());

            Assert.That(async() => await pipe.Send(context), Throws.InvalidOperationException);

            //Console.WriteLine(exception.Message);
        }
示例#2
0
        public async Task Should_allow_just_enough_threads_at_once()
        {
            int currentCount = 0;
            int maxCount     = 0;

            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseConcurrencyLimit(32);
                x.UseExecuteAsync(async payload =>
                {
                    int current = Interlocked.Increment(ref currentCount);
                    while (current > maxCount)
                    {
                        Interlocked.CompareExchange(ref maxCount, current, maxCount);
                    }

                    await Task.Delay(10);

                    Interlocked.Decrement(ref currentCount);
                });
            });

            var context = new TestConsumeContext <A>(new A());

            Task[] tasks = Enumerable.Range(0, 500)
                           .Select(index => Task.Run(async() => await pipe.Send(context)))
                           .ToArray();

            await Task.WhenAll(tasks);

            maxCount.ShouldBe(32);
        }
        public void Should_properly_handle_exception()
        {
            IPipe<ConsumeContext> pipe = Pipe.New<ConsumeContext>(x =>
            {
                x.UseTransaction();
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(async payload =>
                {
                    await Task.Yield();

                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);

                        scope.Complete();
                    }

                    throw new InvalidOperationException("This is a friendly boom");
                });
                x.UseExecute(payload => Console.WriteLine("After Transaction: {0}", Thread.CurrentThread.ManagedThreadId));
            });

            var context = new TestConsumeContext<PingMessage>(new PingMessage());

            Assert.That(async () => await pipe.Send(context), Throws.InvalidOperationException);

            //Console.WriteLine(exception.Message);
        }
        public async Task FeatureToggleShowDeployedEnvironmentIsUpdatedCorrectly()
        {
            //arrange
            var app = Application.Create("TestApp", "DEV", false);

            app.AddFeatureToggle("TestToggle-1", "TestNotes-1", "workItemId1");
            app.AddFeatureToggle("TestToggle-2", "TestNotes-2", "workItemId2");

            await _appRepository.AddAsync(app);

            FeatureToggleTestHelper.UpdateFeatureToggleDeployedStatus(app, "TestToggle-1", "DEV", true);

            var context = new TestConsumeContext <RegisteredTogglesUpdate>(new RegisteredTogglesUpdate
            {
                Environment    = "dev",
                AppName        = "testapp",
                FeatureToggles = new [] { "TestToggle-2" }
            });

            //act
            _sut = new FeatureToggleDeployStatusConsumer(_appRepository);
            await _sut.Consume(context);

            //assert
            var updatedApp = await _appRepository.FindByIdAsync(app.Id);

            FeatureToggleTestHelper.GetFeatureToggleDeployedStatus(updatedApp, "TestToggle-1", "DEV").Should().BeFalse();
            FeatureToggleTestHelper.GetFeatureToggleDeployedStatus(updatedApp, "TestToggle-2", "DEV").Should().BeTrue();
        }
        public async Task Should_allow_the_first_call()
        {
            var count = 0;
            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseCircuitBreaker(v =>
                {
                    v.ResetInterval = TimeSpan.FromSeconds(60);
                    v.Handle<IntentionalTestException>();
                });
                x.UseExecute(payload =>
                {
                    Interlocked.Increment(ref count);

                    throw new IntentionalTestException();
                });
            });

            var context = new TestConsumeContext<A>(new A());

            for (var i = 0; i < 100; i++)
                Assert.That(async () => await pipe.Send(context), Throws.TypeOf<IntentionalTestException>());

            count.ShouldBe(6);
        }
        public async Task Should_allow_just_enough_threads_at_once()
        {
            int currentCount = 0;
            int maxCount = 0;

            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseConcurrencyLimit(32);
                x.UseExecuteAsync(async payload =>
                {
                    int current = Interlocked.Increment(ref currentCount);
                    while (current > maxCount)
                        Interlocked.CompareExchange(ref maxCount, current, maxCount);

                    await Task.Delay(10);

                    Interlocked.Decrement(ref currentCount);
                });
            });

            var context = new TestConsumeContext<A>(new A());

            Task[] tasks = Enumerable.Range(0, 500)
                .Select(index => Task.Run(async () => await pipe.Send(context)))
                .ToArray();

            await Task.WhenAll(tasks);

            maxCount.ShouldBe(32);
        }
示例#7
0
        public void Just_how_fast_are_you()
        {
            var message = new SerializationTestMessage
            {
                DecimalValue  = 123.45m,
                LongValue     = 098123213,
                BoolValue     = true,
                ByteValue     = 127,
                IntValue      = 123,
                DateTimeValue = new DateTime(2008, 9, 8, 7, 6, 5, 4),
                TimeSpanValue = TimeSpan.FromSeconds(30),
                GuidValue     = Guid.NewGuid(),
                StringValue   = "Chris's Sample Code",
                DoubleValue   = 1823.172
            };

            var            sendContext    = new MessageSendContext <SerializationTestMessage>(message);
            ReceiveContext receiveContext = null;

            //warm it up
            for (var i = 0; i < 10; i++)
            {
                byte[] data = Serialize(sendContext);

                var transportMessage = new InMemoryTransportMessage(Guid.NewGuid(), data, Serializer.ContentType.MediaType,
                                                                    TypeMetadataCache <SerializationTestMessage> .ShortName);
                receiveContext = new InMemoryReceiveContext(transportMessage, TestConsumeContext.GetContext());

                Deserialize <SerializationTestMessage>(receiveContext);
            }

            var timer = Stopwatch.StartNew();

            const int iterations = 50000;

            for (var i = 0; i < iterations; i++)
            {
                Serialize(sendContext);
            }

            timer.Stop();

            var perSecond = iterations * 1000 / timer.ElapsedMilliseconds;

            Console.WriteLine("Serialize: {0}ms, Rate: {1} m/s", timer.ElapsedMilliseconds, perSecond);


            timer = Stopwatch.StartNew();

            for (var i = 0; i < 50000; i++)
            {
                Deserialize <SerializationTestMessage>(receiveContext);
            }

            timer.Stop();

            perSecond = iterations * 1000 / timer.ElapsedMilliseconds;

            Console.WriteLine("Deserialize: {0}ms, Rate: {1} m/s", timer.ElapsedMilliseconds, perSecond);
        }
示例#8
0
        public async Task Should_keep_track_of_only_the_last_value()
        {
            ILatestFilter <ConsumeContext <A> > latestFilter = null;

            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseLatest(l => l.Created = filter => latestFilter = filter);
                x.UseExecute(payload =>
                {
                });
            });

            latestFilter.ShouldNotBe(null);

            for (int i = 0; i <= 100; i++)
            {
                var context = new TestConsumeContext <A>(new A {
                    Index = i
                });
                await pipe.Send(context);
            }

            ConsumeContext <A> latest = await latestFilter.Latest;

            latest.Message.Index.ShouldBe(100);
        }
        public async Task Should_allow_the_first_call()
        {
            var count = 0;
            IPipe <ConsumeContext <Running_two_in_memory_transports.A> > pipe = Pipe.New <ConsumeContext <Running_two_in_memory_transports.A> >(x =>
            {
                x.UseCircuitBreaker(v =>
                {
                    v.ResetInterval = TimeSpan.FromSeconds(60);
                    v.Handle <IntentionalTestException>();
                });
                x.UseExecute(payload =>
                {
                    Interlocked.Increment(ref count);

                    throw new IntentionalTestException();
                });
            });

            var context = new TestConsumeContext <Running_two_in_memory_transports.A>(new Running_two_in_memory_transports.A());

            for (var i = 0; i < 100; i++)
            {
                Assert.That(async() => await pipe.Send(context), Throws.TypeOf <IntentionalTestException>());
            }

            count.ShouldBe(6);
        }
示例#10
0
        public async Task Should_prevent_too_many_threads_at_one_time()
        {
            var currentCount = 0;
            var maxCount     = 0;

            IPipe <ConsumeContext <Running_two_in_memory_transports.A> > pipe = Pipe.New <ConsumeContext <Running_two_in_memory_transports.A> >(x =>
            {
                x.UseConcurrencyLimit(1);
                x.UseExecuteAsync(async payload =>
                {
                    var current = Interlocked.Increment(ref currentCount);
                    while (current > maxCount)
                    {
                        Interlocked.CompareExchange(ref maxCount, current, maxCount);
                    }

                    await Task.Delay(10);

                    Interlocked.Decrement(ref currentCount);
                });
            });

            var context = new TestConsumeContext <Running_two_in_memory_transports.A>(new Running_two_in_memory_transports.A());

            Task[] tasks = Enumerable.Range(0, 50)
                           .Select(index => Task.Run(async() => await pipe.Send(context)))
                           .ToArray();

            await Task.WhenAll(tasks);

            maxCount.ShouldBe(1);
        }
示例#11
0
        public void Should_timeout()
        {
            IPipe <ConsumeContext> pipe = Pipe.New <ConsumeContext>(x =>
            {
                x.UseTransaction(t => t.Timeout = TimeSpan.FromSeconds(1));
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(async payload =>
                {
                    await Task.Yield();

                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);

                        Thread.Sleep(2000);

                        scope.Complete();
                    }

                    Console.WriteLine("Exited Scope");
                });
                x.UseExecute(payload => Console.WriteLine("After Transaction: {0}", Thread.CurrentThread.ManagedThreadId));
            });

            var context = new TestConsumeContext <PingMessage>(new PingMessage());

            Assert.That(async() => await pipe.Send(context), Throws.TypeOf <TransactionAbortedException>());

            //Console.WriteLine(exception.Message);
        }
示例#12
0
        public async Task Should_only_do_n_messages_per_interval()
        {
            int count = 0;
            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseRateLimit(10, TimeSpan.FromSeconds(1));
                x.UseExecute(payload =>
                {
                    Interlocked.Increment(ref count);
                });
            });

            var context = new TestConsumeContext <A>(new A());

            var timer = Stopwatch.StartNew();

            Task[] tasks = Enumerable.Range(0, 101)
                           .Select(index => Task.Run(async() => await pipe.Send(context)))
                           .ToArray();

            await Task.WhenAll(tasks);

            timer.Stop();

            timer.ElapsedMilliseconds.ShouldBeGreaterThan(9500);
        }
示例#13
0
        public void Should_support_overloading_downstream_on_cc()
        {
            int count = 0;
            IPipe <ConsumeContext> pipe = Pipe.New <ConsumeContext>(x =>
            {
                x.UseRetry(r =>
                {
                    r.Handle <IntentionalTestException>();
                    r.Interval(4, TimeSpan.FromMilliseconds(2));
                });
                x.UseRetry(r =>
                {
                    r.Handle <IntentionalTestException>();
                    r.None();
                });
                x.UseDispatch(new ConsumeContextConverterFactory(), d =>
                {
                    d.Pipe <ConsumeContext <A> >(a =>
                    {
                        a.UseExecute(payload =>
                        {
                            count++;
                            throw new IntentionalTestException("Kaboom!");
                        });
                    });
                });
            });

            var context = new TestConsumeContext <A>(new A());

            Assert.That(async() => await pipe.Send(context), Throws.TypeOf <IntentionalTestException>());

            count.ShouldBe(1);
        }
示例#14
0
        public void Should_convert_a_simple_correlation_expression()
        {
            var message = new CorrelatedMessage {
                CorrelationId = NewId.NextGuid()
            };
            ConsumeContext <CorrelatedMessage> consumeContext = new TestConsumeContext <CorrelatedMessage>(message);
            var converter = new EventCorrelationExpressionConverter <TestState, CorrelatedMessage>(consumeContext);

            Expression <Func <TestState, bool> > result = converter
                                                          .Convert((state, context) => state.CorrelationId == context.Message.CorrelationId);

            Console.WriteLine(result);
        }
        public void Should_convert_a_simple_correlation_expression()
        {
            var message = new CorrelatedMessage
            {
                CorrelationId = NewId.NextGuid()
            };
            ConsumeContext<CorrelatedMessage> consumeContext = new TestConsumeContext<CorrelatedMessage>(message);
            var converter = new EventCorrelationExpressionConverter<TestState, CorrelatedMessage>(consumeContext);

            Expression<Func<TestState, bool>> result = converter
                .Convert((state, context) => state.CorrelationId == context.Message.CorrelationId);

            Console.WriteLine(result);
        }
示例#16
0
        public async Task Should_receive_a_test_message()
        {
            IConsumePipe filter = CreateConsumePipe();

            TaskCompletionSource <PingMessage> received = GetTask <PingMessage>();

            ConnectHandle connectHandle = filter.ConnectHandler <PingMessage>(async context =>
                                                                              received.TrySetResult(context.Message));

            var consumeContext = new TestConsumeContext <PingMessage>(new PingMessage());

            await filter.Send(consumeContext);

            await received.Task;
        }
        public async Task Should_receive_a_test_message()
        {
            IConsumePipe filter = CreateConsumePipe();

            TaskCompletionSource<PingMessage> received = GetTask<PingMessage>();

            ConnectHandle connectHandle = filter.ConnectHandler<PingMessage>(async context =>
                received.TrySetResult(context.Message));

            var consumeContext = new TestConsumeContext<PingMessage>(new PingMessage());

            await filter.Send(consumeContext);

            await received.Task;
        }
示例#18
0
        public async Task Should_receive_a_message_via_object()
        {
            IConsumePipe filter = CreateConsumePipe();

            OneMessageConsumer consumer = GetOneMessageConsumer();

            object subscribeConsumer = consumer;

            filter.ConnectInstance(subscribeConsumer);

            var consumeContext = new TestConsumeContext <MessageA>(new MessageA());

            await filter.Send(consumeContext);

            await consumer.Task;
        }
        public async Task Should_receive_a_message_via_object()
        {
            IConsumePipe filter = CreateConsumePipe();

            OneMessageConsumer consumer = GetOneMessageConsumer();

            object subscribeConsumer = consumer;

            filter.ConnectInstance(subscribeConsumer);

            var consumeContext = new TestConsumeContext<MessageA>(new MessageA());

            await filter.Send(consumeContext);

            await consumer.Task;
        }
        public async Task Should_receive_a_message()
        {
            IConsumePipe filter = CreateConsumePipe();

            OneMessageConsumer consumer = GetOneMessageConsumer();

            IConsumerFactory<OneMessageConsumer> factory = GetInstanceConsumerFactory(consumer);

            filter.ConnectConsumer(factory);

            var consumeContext = new TestConsumeContext<MessageA>(new MessageA());

            await filter.Send(consumeContext);

            await consumer.Task;
        }
示例#21
0
        public async Task Should_receive_a_message()
        {
            IConsumePipe filter = CreateConsumePipe();

            OneMessageConsumer consumer = GetOneMessageConsumer();

            IConsumerFactory <OneMessageConsumer> factory = GetInstanceConsumerFactory(consumer);

            filter.ConnectConsumer(factory);

            var consumeContext = new TestConsumeContext <MessageA>(new MessageA());

            await filter.Send(consumeContext);

            await consumer.Task;
        }
示例#22
0
        public void When_all_check_passes_should_call_Executeworkflow()
        {
            _userService.Setup(x => x.GetUserAsync(It.IsAny <string>()))
            .ReturnsAsync(() => null);

            _workflowActivityServiceMock.Setup(x => x.IsUserBeingCreated(It.IsAny <string>())).Returns(false);

            var createUserConsumer = CreateCreateUserConsumerInstance();
            var consumeContext     = new TestConsumeContext <ICreateUserCommand>(new CreateUserCommandTest
            {
                Email = "*****@*****.**"
            });

            createUserConsumer.Consume(consumeContext);

            _createUserWorkflowBuilderMock.Verify(x => x.Execute(consumeContext));
        }
示例#23
0
        public void Should_retry_the_specified_times_and_fail()
        {
            int count = 0;
            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseRetry(Retry.Interval(4, TimeSpan.FromMilliseconds(2)));
                x.UseExecute(payload =>
                {
                    count++;
                    throw new IntentionalTestException("Kaboom!");
                });
            });

            var context = new TestConsumeContext <A>(new A());

            Assert.That(async() => await pipe.Send(context), Throws.TypeOf <IntentionalTestException>());

            count.ShouldBe(5);
        }
示例#24
0
        public void Should_retry_the_specified_times_and_fail()
        {
            int count = 0;
            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseRetry(Retry.Interval(4, TimeSpan.FromMilliseconds(2)));
                x.UseExecute(payload =>
                {
                    count++;
                    throw new IntentionalTestException("Kaboom!");
                });
            });

            var context = new TestConsumeContext<A>(new A());

            var exception = Assert.Throws<IntentionalTestException>(async () => await pipe.Send(context));

            count.ShouldBe(5);
        }
示例#25
0
        public void Should_support_overloading_downstream_either_way()
        {
            int count = 0;
            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseRetry(Retry.None);
                x.UseRetry(Retry.Interval(4, TimeSpan.FromMilliseconds(2)));
                x.UseExecute(payload =>
                {
                    count++;
                    throw new IntentionalTestException("Kaboom!");
                });
            });

            var context = new TestConsumeContext <A>(new A());

            Assert.That(async() => await pipe.Send(context), Throws.TypeOf <IntentionalTestException>());

            count.ShouldBe(5);
        }
示例#26
0
        public void Should_support_overloading_downstream()
        {
            int count = 0;
            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseRetry(Retry.Interval(4, TimeSpan.FromMilliseconds(2)));
                x.UseRetry(Retry.None);
                x.UseExecute(payload =>
                {
                    count++;
                    throw new IntentionalTestException("Kaboom!");
                });
            });

            var context = new TestConsumeContext<A>(new A());

            var exception = Assert.Throws<IntentionalTestException>(async () => await pipe.Send(context));

            count.ShouldBe(1);
        }
示例#27
0
        protected T Return <T>(byte[] serializedMessageData)
            where T : class
        {
            var message        = new InMemoryTransportMessage(Guid.NewGuid(), serializedMessageData, Serializer.ContentType.MediaType, TypeMetadataCache <T> .ShortName);
            var receiveContext = new InMemoryReceiveContext(message, TestConsumeContext.GetContext());

            var consumeContext = Deserializer.Deserialize(receiveContext);

            consumeContext.TryGetMessage(out ConsumeContext <T> messageContext);

            messageContext.ShouldNotBe(null);

            messageContext.SourceAddress.ShouldBe(_sourceAddress);
            messageContext.DestinationAddress.ShouldBe(_destinationAddress);
            messageContext.FaultAddress.ShouldBe(_faultAddress);
            messageContext.ResponseAddress.ShouldBe(_responseAddress);
            messageContext.RequestId.HasValue.ShouldBe(true);
            messageContext.RequestId.Value.ShouldBe(_requestId);

            return(messageContext.Message);
        }
示例#28
0
        public async Task Should_count_success_and_failure_as_same()
        {
            int count = 0;
            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseRateLimit(10, TimeSpan.FromSeconds(1));
                x.UseExecute(payload =>
                {
                    var index = Interlocked.Increment(ref count);
                    if (index % 2 == 0)
                    {
                        throw new IntentionalTestException();
                    }
                });
            });

            var context = new TestConsumeContext <A>(new A());

            var timer = Stopwatch.StartNew();

            Task[] tasks = Enumerable.Range(0, 101)
                           .Select(index => Task.Run(async() =>
            {
                try
                {
                    await pipe.Send(context);
                }
                catch (Exception)
                {
                }
            }))
                           .ToArray();

            await Task.WhenAll(tasks);

            timer.Stop();

            timer.ElapsedMilliseconds.ShouldBeGreaterThan(9500);
        }
示例#29
0
        public async Task Should_properly_succeed()
        {
            IPipe <ConsumeContext> pipe = Pipe.New <ConsumeContext>(x =>
            {
                x.UseTransaction();
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(payload => Task.Run(() =>
                {
                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);
                        scope.Complete();
                    }
                }));
            });

            var context = new TestConsumeContext <PingMessage>(new PingMessage());

            await pipe.Send(context);
        }
        public async Task Should_allow_the_first_call()
        {
            int count = 0;
            IPipe <ConsumeContext <A> > pipe = Pipe.New <ConsumeContext <A> >(x =>
            {
                x.UseCircuitBreaker(v => v.ResetInterval(TimeSpan.FromSeconds(60)));
                x.UseExecute(payload =>
                {
                    Interlocked.Increment(ref count);

                    throw new IntentionalTestException();
                });
            });

            var context = new TestConsumeContext <A>(new A());

            for (int i = 0; i < 100; i++)
            {
                Assert.Throws <IntentionalTestException>(async() => await pipe.Send(context));
            }

            count.ShouldBe(6);
        }
示例#31
0
        public void Should_properly_fail()
        {
            IPipe <ConsumeContext> pipe = Pipe.New <ConsumeContext>(x =>
            {
                x.UseTransaction();
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(payload => Task.Run(() =>
                {
                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);
                    }
                }));
            });

            var context = new TestConsumeContext <PingMessage>(new PingMessage());

            Assert.That(async() => await pipe.Send(context), Throws.TypeOf <TransactionAbortedException>());

            //Console.WriteLine(exception.Message);
        }
        public async Task Should_keep_track_of_only_the_last_value()
        {
            ILatestFilter<ConsumeContext<A>> latestFilter = null;

            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseLatest(l => l.Created = filter => latestFilter = filter);
                x.UseExecute(payload =>
                {
                });
            });

            latestFilter.ShouldNotBe(null);

            for (int i = 0; i <= 100; i++)
            {
                var context = new TestConsumeContext<A>(new A {Index = i});
                await pipe.Send(context);
            }

            ConsumeContext<A> latest = await latestFilter.Latest;

            latest.Message.Index.ShouldBe(100);
        }
        public void Should_properly_fail()
        {
            IPipe<ConsumeContext> pipe = Pipe.New<ConsumeContext>(x =>
            {
                x.UseTransaction();
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(payload => Task.Run(() =>
                {
                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);
                    }
                }));
            });

            var context = new TestConsumeContext<PingMessage>(new PingMessage());

            Assert.That(async () => await pipe.Send(context), Throws.TypeOf<TransactionAbortedException>());

            //Console.WriteLine(exception.Message);
        }
        public void Should_timeout()
        {
            IPipe<ConsumeContext> pipe = Pipe.New<ConsumeContext>(x =>
            {
                x.UseTransaction(t => t.Timeout = TimeSpan.FromSeconds(1));
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(async payload =>
                {
                    await Task.Yield();

                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);

                        Thread.Sleep(2000);

                        scope.Complete();
                    }

                    Console.WriteLine("Exited Scope");
                });
                x.UseExecute(payload => Console.WriteLine("After Transaction: {0}", Thread.CurrentThread.ManagedThreadId));
            });

            var context = new TestConsumeContext<PingMessage>(new PingMessage());

            Assert.That(async () => await pipe.Send(context), Throws.TypeOf<TransactionAbortedException>());

            //Console.WriteLine(exception.Message);
        }
        public async Task Should_count_success_and_failure_as_same()
        {
            int count = 0;
            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseRateLimit(10, TimeSpan.FromSeconds(1));
                x.UseExecute(payload =>
                {
                    var index = Interlocked.Increment(ref count);
                    if (index % 2 == 0)
                        throw new IntentionalTestException();
                });
            });

            var context = new TestConsumeContext<A>(new A());

            var timer = Stopwatch.StartNew();

            Task[] tasks = Enumerable.Range(0, 101)
                .Select(index => Task.Run(async () =>
                {
                    try
                    {
                        await pipe.Send(context);
                    }
                    catch (Exception)
                    {
                    }
                }))
                .ToArray();

            await Task.WhenAll(tasks);

            timer.Stop();

            timer.ElapsedMilliseconds.ShouldBeGreaterThan(9500);
        }
        public async Task Should_only_do_n_messages_per_interval()
        {
            int count = 0;
            IPipe<ConsumeContext<A>> pipe = Pipe.New<ConsumeContext<A>>(x =>
            {
                x.UseRateLimit(10, TimeSpan.FromSeconds(1));
                x.UseExecute(payload =>
                {
                    Interlocked.Increment(ref count);
                });
            });

            var context = new TestConsumeContext<A>(new A());

            var timer = Stopwatch.StartNew();

            Task[] tasks = Enumerable.Range(0, 101)
                .Select(index => Task.Run(async () => await pipe.Send(context)))
                .ToArray();

            await Task.WhenAll(tasks);

            timer.Stop();

            timer.ElapsedMilliseconds.ShouldBeGreaterThan(9500);
        }
        public async Task Should_properly_succeed()
        {
            IPipe<ConsumeContext> pipe = Pipe.New<ConsumeContext>(x =>
            {
                x.UseTransaction();
                x.UseExecute(payload => Console.WriteLine("Execute: {0}", Thread.CurrentThread.ManagedThreadId));
                x.UseExecuteAsync(payload => Task.Run(() =>
                {
                    using (TransactionScope scope = payload.CreateTransactionScope())
                    {
                        Console.WriteLine("ExecuteAsync: {0}", Thread.CurrentThread.ManagedThreadId);

                        Assert.IsNotNull(Transaction.Current);
                        Console.WriteLine("Isolation Level: {0}", Transaction.Current.IsolationLevel);
                        scope.Complete();
                    }
                }));
            });

            var context = new TestConsumeContext<PingMessage>(new PingMessage());

            await pipe.Send(context);
        }