Exemplo n.º 1
0
        public void Command_SemaphorePermitsInUse()
        {
            TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();

            // this semaphore will be shared across multiple command instances
            TryableSemaphore sharedSemaphore =
                new TryableSemaphore(HystrixPropertyFactory.AsProperty(3));

            // used to wait until all commands have started
            CountdownEvent startLatch = new CountdownEvent(sharedSemaphore.NumberOfPermits.Get() + 1);

            // used to signal that all command can finish
            CountdownEvent sharedLatch = new CountdownEvent(1);

            IRunnable sharedSemaphoreRunnable = new HystrixContextRunnable(new Runnable(() =>
            {
                try
                {
                    new LatchedSemaphoreCommand(circuitBreaker, sharedSemaphore, startLatch, sharedLatch).Execute();
                }
                catch (Exception)
                {

                }
            }));

            // creates group of threads each using command sharing a single semaphore

            // I create extra threads and commands so that I can verify that some of them fail to obtain a semaphore
            int sharedThreadCount = sharedSemaphore.NumberOfPermits.Get() * 2;
            Thread[] sharedSemaphoreThreads = new Thread[sharedThreadCount];
            for (int i = 0; i < sharedThreadCount; i++)
            {
                sharedSemaphoreThreads[i] = new Thread(sharedSemaphoreRunnable.Run);
            }

            // creates thread using isolated semaphore
            TryableSemaphore isolatedSemaphore =
                new TryableSemaphore(HystrixPropertyFactory.AsProperty(1));

            CountdownEvent isolatedLatch = new CountdownEvent(1);

            // tracks failures to obtain semaphores
            AtomicInteger failureCount = new AtomicInteger();

            Thread isolatedThread = new Thread(new HystrixContextRunnable(new Runnable(() =>
            {
                try
                {
                    new LatchedSemaphoreCommand(circuitBreaker, isolatedSemaphore, startLatch, isolatedLatch).Execute();
                }
                catch (Exception)
                {

                    failureCount.IncrementAndGet();
                }
            })).Run);

            // verifies no permits in use before starting threads
            Assert.AreEqual(0, sharedSemaphore.GetNumberOfPermitsUsed(), "wrong number of permits for shared semaphore");
            Assert.AreEqual(0, isolatedSemaphore.GetNumberOfPermitsUsed(), "wrong number of permits for isolated semaphore");

            for (int i = 0; i < sharedThreadCount; i++)
            {
                sharedSemaphoreThreads[i].Start();
            }
            isolatedThread.Start();

            // waits until all commands have started
            try
            {
                startLatch.Wait(TimeSpan.FromSeconds(1.0));
            }
            catch (ThreadInterruptedException e)
            {
                throw new Exception("Unexpected exception.", e);
            }

            // verifies that all semaphores are in use
            Assert.AreEqual(sharedSemaphore.NumberOfPermits.Get(), sharedSemaphore.GetNumberOfPermitsUsed(), "wrong number of permits for shared semaphore");
            Assert.AreEqual(isolatedSemaphore.NumberOfPermits.Get(), isolatedSemaphore.GetNumberOfPermitsUsed(), "wrong number of permits for isolated semaphore");

            // signals commands to finish
            sharedLatch.Signal();
            isolatedLatch.Signal();

            try
            {
                for (int i = 0; i < sharedThreadCount; i++)
                {
                    sharedSemaphoreThreads[i].Join();
                }
                isolatedThread.Join();
            }
            catch (Exception)
            {

                Assert.Fail("failed waiting on threads");
            }

            // verifies no permits in use after finishing threads
            Assert.AreEqual(0, sharedSemaphore.GetNumberOfPermitsUsed(), "wrong number of permits for shared semaphore");
            Assert.AreEqual(0, isolatedSemaphore.GetNumberOfPermitsUsed(), "wrong number of permits for isolated semaphore");

            // verifies that some executions failed
            int expectedFailures = sharedSemaphore.GetNumberOfPermitsUsed();
            Assert.AreEqual(expectedFailures, failureCount.Value, "failures expected but did not happen");
            Hystrix.Reset();
        }
Exemplo n.º 2
0
        public void Command_ExecutionSemaphoreWithExecution()
        {
            TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
            // single thread should work
            try
            {
                TestSemaphoreCommand command = new TestSemaphoreCommand(circuitBreaker, 1, TimeSpan.FromMilliseconds(200));
                bool result = command.Execute();
                Assert.IsFalse(command.IsExecutedInThread);
                Assert.IsTrue(result);
            }
            catch (Exception e)
            {
                // we shouldn't fail on this one
                throw new Exception("Unexpected exception.", e);
            }

            ArrayBlockingQueue<bool> results = new ArrayBlockingQueue<bool>(2);

            AtomicBoolean exceptionReceived = new AtomicBoolean();

            TryableSemaphore semaphore =
                new TryableSemaphore(HystrixPropertyFactory.AsProperty(1));

            IRunnable r = new HystrixContextRunnable(new Runnable(() =>
            {
                try
                {
                    results.Add(new TestSemaphoreCommand(circuitBreaker, semaphore, TimeSpan.FromMilliseconds(200)).Execute());
                }
                catch (Exception)
                {

                    exceptionReceived.Value = true;
                }
            }));

            // 2 threads, the second should be rejected by the semaphore
            Thread t1 = new Thread(r.Run);
            Thread t2 = new Thread(r.Run);

            t1.Start();
            t2.Start();
            try
            {
                t1.Join();
                t2.Join();
            }
            catch (Exception)
            {

                Assert.Fail("failed waiting on threads");
            }

            if (!exceptionReceived.Value)
            {
                Assert.Fail("We expected an exception on the 2nd get");
            }

            // only 1 value is expected as the other should have thrown an exception
            Assert.AreEqual(1, results.Count);
            // should contain only a true result
            Assert.IsTrue(results.Contains(true));
            Assert.IsFalse(results.Contains(false));

            Assert.AreEqual(2, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Success));
            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ExceptionThrown));
            // no failure ... we throw an exception because of rejection but the command does not fail execution
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Failure));
            // there is no fallback implemented so no failure can occur on it
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackFailure));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackRejection));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackSuccess));
            // we rejected via semaphore
            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.SemaphoreRejected));
            // the rest should not be involved in this test
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ShortCircuited));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ThreadPoolRejected));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Timeout));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ResponseFromCache));

            Assert.AreEqual(3, HystrixRequestLog.GetCurrentRequest().ExecutedCommands.Count());
            Hystrix.Reset();
        }
Exemplo n.º 3
0
        public void Command_RejectedExecutionSemaphoreWithFallback()
        {
            TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
            ArrayBlockingQueue<bool> results = new ArrayBlockingQueue<bool>(2);

            AtomicBoolean exceptionReceived = new AtomicBoolean();

            IRunnable r = new HystrixContextRunnable(new Runnable(() =>
            {
                try
                {
                    results.Add(new TestSemaphoreCommandWithFallback(circuitBreaker, 1, TimeSpan.FromMilliseconds(200), false).Execute());
                }
                catch (Exception)
                {

                    exceptionReceived.Value = true;
                }
            }));

            // 2 threads, the second should be rejected by the semaphore and return fallback
            Thread t1 = new Thread(r.Run);
            Thread t2 = new Thread(r.Run);

            t1.Start();
            t2.Start();
            try
            {
                t1.Join();
                t2.Join();
            }
            catch (Exception)
            {

                Assert.Fail("failed waiting on threads");
            }

            if (exceptionReceived.Value)
            {
                Assert.Fail("We should have received a fallback response");
            }

            // both threads should have returned values
            Assert.AreEqual(2, results.Count);
            // should contain both a true and false result
            Assert.IsTrue(results.Contains(true));
            Assert.IsTrue(results.Contains(false));

            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Success));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ExceptionThrown));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Failure));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackFailure));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackRejection));
            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackSuccess));
            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.SemaphoreRejected));
            // the rest should not be involved in this test
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ShortCircuited));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ThreadPoolRejected));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Timeout));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ResponseFromCache));

            TestContext.WriteLine("**** DONE");

            Assert.AreEqual(2, HystrixRequestLog.GetCurrentRequest().ExecutedCommands.Count());
            Hystrix.Reset();
        }
Exemplo n.º 4
0
        public void Command_ExecutionSemaphoreWithQueue()
        {
            TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
            // single thread should work
            try
            {
                bool result = new TestSemaphoreCommand(circuitBreaker, 1, TimeSpan.FromMilliseconds(200)).Queue().Get();
                Assert.IsTrue(result);
            }
            catch (Exception e)
            {
                // we shouldn't fail on this one
                throw new Exception("Unexpected exception.", e);
            }

            AtomicBoolean exceptionReceived = new AtomicBoolean();

            TryableSemaphore semaphore =
                new TryableSemaphore(HystrixPropertyFactory.AsProperty(1));

            IRunnable r = new HystrixContextRunnable(new Runnable(() =>
            {
                try
                {
                    new TestSemaphoreCommand(circuitBreaker, semaphore, TimeSpan.FromMilliseconds(200)).Queue().Get();
                }
                catch (Exception)
                {

                    exceptionReceived.Value = true;
                }
            }));
            // 2 threads, the second should be rejected by the semaphore
            Thread t1 = new Thread(r.Run);
            Thread t2 = new Thread(r.Run);

            t1.Start();
            t2.Start();
            try
            {
                t1.Join();
                t2.Join();
            }
            catch (Exception)
            {

                Assert.Fail("failed waiting on threads");
            }

            if (!exceptionReceived.Value)
            {
                Assert.Fail("We expected an exception on the 2nd get");
            }

            Assert.AreEqual(2, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Success));
            // we don't have a fallback so threw an exception when rejected
            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ExceptionThrown));
            // not a failure as the command never executed so can't fail
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Failure));
            // no fallback failure as there isn't a fallback implemented
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackFailure));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackRejection));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackSuccess));
            // we should have rejected via semaphore
            Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.SemaphoreRejected));
            // the rest should not be involved in this test
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ShortCircuited));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ThreadPoolRejected));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Timeout));
            Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ResponseFromCache));

            Assert.AreEqual(3, HystrixRequestLog.GetCurrentRequest().ExecutedCommands.Count());
            Hystrix.Reset();
        }