예제 #1
0
        public async Task Should_allow_dynamic_reconfiguration_down()
        {
            var router = new PipeRouter();
            int count  = 0;
            IPipe <InputContext> pipe = Pipe.New <InputContext>(cfg =>
            {
                cfg.UseRateLimit(100, TimeSpan.FromSeconds(1), router);
                cfg.UseExecute(cxt =>
                {
                    Interlocked.Increment(ref count);
                });
            });

            await router.SetRateLimit(10);

            var context = new InputContext("Hello");

            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();

            Assert.That(timer.ElapsedMilliseconds, Is.GreaterThan(9500));
        }
예제 #2
0
        public void Should_be_called_when_send_faulted()
        {
            IPipeRouter router = new PipeRouter();

            router.ConnectPipe(Pipe.New <CommandContext <SetConcurrencyLimit> >(cfg =>
            {
                cfg.UseExecute(cxt =>
                {
                    throw new IntentionalTestException("Wow!");
                });
            }));

            var observer = new Observer <CommandContext <SetConcurrencyLimit> >();

            router.ConnectObserver(observer);

            var observer2 = new Observer();

            router.ConnectObserver(observer2);

            Assert.That(async() => await router.SetConcurrencyLimit(32), Throws.TypeOf <IntentionalTestException>());

            Assert.That(async() => await observer.SendFaulted, Throws.TypeOf <IntentionalTestException>());

            Assert.That(async() => await observer2.SendFaulted, Throws.TypeOf <IntentionalTestException>());
        }
예제 #3
0
        public SendBenchmark()
        {
            _context = new ThroughputTestContext(Guid.NewGuid(), "Payload");

            _emptyPipe = Pipe.Empty <TestContext>();

            _retryPipe = Pipe.New <TestContext>(x =>
            {
                x.UseRetry(r => r.Immediate(1));

                x.UseFilter(new BenchmarkFilter());
            });

            _concurrencyPipe = Pipe.New <TestContext>(x =>
            {
                x.UseConcurrencyLimit(Environment.ProcessorCount);

                x.UseFilter(new BenchmarkFilter());
            });

            _doublePipe = Pipe.New <TestContext>(x =>
            {
                x.UseConcurrencyLimit(Environment.ProcessorCount);
                x.UseRetry(r => r.Immediate(1));

                x.UseFilter(new BenchmarkFilter());
            });

            _faultPipe = Pipe.New <TestContext>(x =>
            {
                x.UseRetry(r => r.Immediate(1));

                x.UseFilter(new FaultFilter());
            });

            var dispatchPipe = new PipeRouter();

            _dispatchPipe = dispatchPipe;

            dispatchPipe.ConnectPipe(Pipe.Empty <CommandContext <SetConcurrencyLimit> >());

            var doubleDispatchPipe = new PipeRouter();

            _doubleDispatchPipe = doubleDispatchPipe;

            doubleDispatchPipe.ConnectPipe(Pipe.Empty <CommandContext <SetConcurrencyLimit> >());
            doubleDispatchPipe.ConnectPipe(Pipe.Empty <CommandContext <SetRateLimit> >());

            var tripleDispatchPipe = new PipeRouter();

            _tripleDispatchPipe = tripleDispatchPipe;

            tripleDispatchPipe.ConnectPipe(Pipe.Empty <CommandContext <SetConcurrencyLimit> >());
            tripleDispatchPipe.ConnectPipe(Pipe.Empty <CommandContext <SetRateLimit> >());
            tripleDispatchPipe.ConnectPipe(Pipe.Empty <CommandContext <CircuitBreakerOpened> >());
        }
예제 #4
0
        public async Task Should_be_called_pre_send()
        {
            IPipeRouter router = new PipeRouter();

            router.ConnectPipe(Pipe.Empty <CommandContext <SetConcurrencyLimit> >());

            var observer = new Observer <CommandContext <SetConcurrencyLimit> >();

            router.ConnectObserver(observer);

            var observer2 = new Observer();

            router.ConnectObserver(observer2);

            await router.SetConcurrencyLimit(32);

            await observer.PreSent;

            Assert.That(async() => await observer2.PreSent, Is.InstanceOf <CommandContext <SetConcurrencyLimit> >());
        }
예제 #5
0
        public async Task Should_support_interaction_between_filters()
        {
            var myFilter = new MyFilter();

            IPipeRouter router = new PipeRouter();

            IPipe <InputContext> pipe = Pipe.New <InputContext>(cfg =>
            {
                cfg.UseConcurrencyLimit(10, router);
                cfg.UseCircuitBreaker(cb =>
                {
                    cb.ActiveThreshold = 5;
                    cb.TrackingPeriod  = TimeSpan.FromSeconds(60);
                    cb.TripThreshold   = 25;
                    cb.ResetInterval   = TimeSpan.FromSeconds(30);

                    cb.Router = router;
                });
                cfg.UseRetry(x => x.Immediate(1));

                cfg.UseFilter(myFilter);
            });

            myFilter.Throw = true;

            router.ConnectPipe(Pipe.New <EventContext <CircuitBreakerOpened> >(x => x.UseFilter(new MyController(router))));


            await Task.WhenAll(Enumerable.Range(0, 140).Select(async index =>
            {
                try
                {
                    await pipe.Send(new InputContext("Hello"));
                }
                catch (Exception ex)
                {
                    await Console.Out.WriteLineAsync($"{DateTime.Now:mm:ss:fff} - Faulted: {ex.Message}");
                }
            }));
        }
예제 #6
0
        public async Task Should_allow_reconfiguration_at_runtime()
        {
            var currentCount = 0;
            var maxCount     = 0;

            IPipeRouter dynamicRouter = new PipeRouter();

            IPipe <InputContext> pipe = Pipe.New <InputContext>(cfg =>
            {
                cfg.UseConcurrencyLimit(1, dynamicRouter);
                cfg.UseExecuteAsync(async cxt =>
                {
                    var current = Interlocked.Increment(ref currentCount);
                    while (current > maxCount)
                    {
                        Interlocked.CompareExchange(ref maxCount, current, maxCount);
                    }

                    await Task.Delay(10);

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

            await dynamicRouter.SendCommand <SetConcurrencyLimit>(new
            {
                ConcurrencyLimit = 32
            });

            var context = new InputContext("Hello");

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

            await Task.WhenAll(tasks);

            Assert.That(maxCount, Is.EqualTo(32));
        }
예제 #7
0
        public async Task Should_allow_the_first_call()
        {
            var router = new PipeRouter();

            var count = 0;
            IPipe <TestContext> pipe = Pipe.New <TestContext>(x =>
            {
                x.UseCircuitBreaker(v =>
                {
                    v.ResetInterval = TimeSpan.FromSeconds(60);
                    v.Router        = router;
                });
                x.UseExecute(payload =>
                {
                    Interlocked.Increment(ref count);

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

            TaskCompletionSource <CircuitBreakerOpened>  opened = TaskUtil.GetTask <CircuitBreakerOpened>();
            IPipe <EventContext <CircuitBreakerOpened> > observeCircuitBreaker =
                Pipe.Execute <EventContext <CircuitBreakerOpened> >(x => opened.TrySetResult(x.Event));

            router.ConnectPipe(observeCircuitBreaker);

            var context = new TestContext();

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

            Assert.That(count, Is.EqualTo(6));

            await opened.Task;
        }