use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.
the class HystrixObservableCommandTest method testRejectedExecutionSemaphoreWithFallback.
@Test
public void testRejectedExecutionSemaphoreWithFallback() {
final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(2);
final AtomicBoolean exceptionReceived = new AtomicBoolean();
final TestSemaphoreCommandWithFallback command1 = new TestSemaphoreCommandWithFallback(circuitBreaker, 1, 200, false);
Runnable r1 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
try {
results.add(command1.observe().toBlocking().single());
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
final TestSemaphoreCommandWithFallback command2 = new TestSemaphoreCommandWithFallback(circuitBreaker, 1, 200, false);
Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
try {
results.add(command2.observe().toBlocking().single());
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
// 2 threads, the second should be rejected by the semaphore and return fallback
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
try {
//give t1 a headstart
Thread.sleep(50);
} catch (InterruptedException ex) {
fail(ex.getMessage());
}
t2.start();
try {
t1.join();
t2.join();
} catch (Exception e) {
e.printStackTrace();
fail("failed waiting on threads");
}
if (exceptionReceived.get()) {
fail("We should have received a fallback response");
}
// both threads should have returned values
assertEquals(2, results.size());
// should contain both a true and false result
assertTrue(results.contains(Boolean.TRUE));
assertTrue(results.contains(Boolean.FALSE));
assertCommandExecutionEvents(command1, HystrixEventType.EMIT, HystrixEventType.SUCCESS);
assertCommandExecutionEvents(command2, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_EMIT, HystrixEventType.FALLBACK_SUCCESS);
assertEquals(0, command1.metrics.getCurrentConcurrentExecutionCount());
assertSaneHystrixRequestLog(2);
}
use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.
the class HealthCountsStreamTest method testSemaphoreRejected.
@Test
public void testSemaphoreRejected() {
HystrixCommandKey key = HystrixCommandKey.Factory.asKey("CMD-Health-H");
stream = HealthCountsStream.getInstance(key, 10, 100);
final CountDownLatch latch = new CountDownLatch(1);
stream.observe().take(10).subscribe(getSubscriber(latch));
//10 commands will saturate semaphore when called from different threads.
//submit 2 more requests and they should be SEMAPHORE_REJECTED
//should see 10 SUCCESSes, 2 SEMAPHORE_REJECTED and 2 FALLBACK_SUCCESSes
List<Command> saturators = new ArrayList<Command>();
for (int i = 0; i < 10; i++) {
saturators.add(CommandStreamTest.Command.from(groupKey, key, HystrixEventType.SUCCESS, 400, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE));
}
CommandStreamTest.Command rejected1 = CommandStreamTest.Command.from(groupKey, key, HystrixEventType.SUCCESS, 0, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE);
CommandStreamTest.Command rejected2 = CommandStreamTest.Command.from(groupKey, key, HystrixEventType.SUCCESS, 0, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE);
for (final CommandStreamTest.Command saturator : saturators) {
new Thread(new HystrixContextRunnable(new Runnable() {
@Override
public void run() {
saturator.observe();
}
})).start();
}
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
fail(ie.getMessage());
}
rejected1.observe();
rejected2.observe();
try {
assertTrue(latch.await(10000, TimeUnit.MILLISECONDS));
} catch (InterruptedException ex) {
fail("Interrupted ex");
}
System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
assertTrue(rejected1.isResponseSemaphoreRejected());
assertTrue(rejected2.isResponseSemaphoreRejected());
assertEquals(2L, stream.getLatest().getErrorCount());
assertEquals(12L, stream.getLatest().getTotalRequests());
}
use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.
the class HystrixObservableCommandTest method testRejectedViaThreadIsolation.
@Test
public void testRejectedViaThreadIsolation() throws InterruptedException {
final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(10);
final List<Thread> executionThreads = Collections.synchronizedList(new ArrayList<Thread>(20));
final List<Thread> responseThreads = Collections.synchronizedList(new ArrayList<Thread>(10));
final AtomicBoolean exceptionReceived = new AtomicBoolean();
final CountDownLatch scheduleLatch = new CountDownLatch(2);
final CountDownLatch successLatch = new CountDownLatch(1);
final AtomicInteger count = new AtomicInteger();
final AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand> command1Ref = new AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand>();
final AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand> command2Ref = new AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand>();
final AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand> command3Ref = new AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand>();
Runnable r1 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
final boolean shouldExecute = count.incrementAndGet() < 3;
try {
executionThreads.add(Thread.currentThread());
TestThreadIsolationWithSemaphoreSetSmallCommand command1 = new TestThreadIsolationWithSemaphoreSetSmallCommand(circuitBreaker, 2, new Action0() {
@Override
public void call() {
// make sure it's deterministic and we put 2 threads into the pool before the 3rd is submitted
if (shouldExecute) {
try {
scheduleLatch.countDown();
successLatch.await();
} catch (InterruptedException e) {
}
}
}
});
command1Ref.set(command1);
results.add(command1.toObservable().map(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean b) {
responseThreads.add(Thread.currentThread());
return b;
}
}).doAfterTerminate(new Action0() {
@Override
public void call() {
if (!shouldExecute) {
// the final thread that shouldn't execute releases the latch once it has run
// so it is deterministic that the other two fill the thread pool until this one rejects
successLatch.countDown();
}
}
}).toBlocking().single());
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
final boolean shouldExecute = count.incrementAndGet() < 3;
try {
executionThreads.add(Thread.currentThread());
TestThreadIsolationWithSemaphoreSetSmallCommand command2 = new TestThreadIsolationWithSemaphoreSetSmallCommand(circuitBreaker, 2, new Action0() {
@Override
public void call() {
// make sure it's deterministic and we put 2 threads into the pool before the 3rd is submitted
if (shouldExecute) {
try {
scheduleLatch.countDown();
successLatch.await();
} catch (InterruptedException e) {
}
}
}
});
command2Ref.set(command2);
results.add(command2.toObservable().map(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean b) {
responseThreads.add(Thread.currentThread());
return b;
}
}).doAfterTerminate(new Action0() {
@Override
public void call() {
if (!shouldExecute) {
// the final thread that shouldn't execute releases the latch once it has run
// so it is deterministic that the other two fill the thread pool until this one rejects
successLatch.countDown();
}
}
}).toBlocking().single());
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
Runnable r3 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
final boolean shouldExecute = count.incrementAndGet() < 3;
try {
executionThreads.add(Thread.currentThread());
TestThreadIsolationWithSemaphoreSetSmallCommand command3 = new TestThreadIsolationWithSemaphoreSetSmallCommand(circuitBreaker, 2, new Action0() {
@Override
public void call() {
// make sure it's deterministic and we put 2 threads into the pool before the 3rd is submitted
if (shouldExecute) {
try {
scheduleLatch.countDown();
successLatch.await();
} catch (InterruptedException e) {
}
}
}
});
command3Ref.set(command3);
results.add(command3.toObservable().map(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean b) {
responseThreads.add(Thread.currentThread());
return b;
}
}).doAfterTerminate(new Action0() {
@Override
public void call() {
if (!shouldExecute) {
// the final thread that shouldn't execute releases the latch once it has run
// so it is deterministic that the other two fill the thread pool until this one rejects
successLatch.countDown();
}
}
}).toBlocking().single());
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
// 2 threads, the second should be rejected by the semaphore and return fallback
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
// wait for the previous 2 thread to be running before starting otherwise it can race
scheduleLatch.await(500, TimeUnit.MILLISECONDS);
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (Exception e) {
e.printStackTrace();
fail("failed waiting on threads");
}
// we should have 2 of the 3 return results
assertEquals(2, results.size());
// the other thread should have thrown an Exception
assertTrue(exceptionReceived.get());
assertCommandExecutionEvents(command1Ref.get(), HystrixEventType.EMIT, HystrixEventType.SUCCESS);
assertCommandExecutionEvents(command2Ref.get(), HystrixEventType.EMIT, HystrixEventType.SUCCESS);
assertCommandExecutionEvents(command3Ref.get(), HystrixEventType.THREAD_POOL_REJECTED, HystrixEventType.FALLBACK_MISSING);
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
assertSaneHystrixRequestLog(3);
}
use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.
the class HystrixObservableCollapserTest method testCollapserUnderConcurrency.
@Test
public void testCollapserUnderConcurrency() throws InterruptedException {
final CollapserTimer timer = new RealCollapserTimer();
final int NUM_THREADS_SUBMITTING_WORK = 8;
final int NUM_REQUESTS_PER_THREAD = 8;
final CountDownLatch latch = new CountDownLatch(NUM_THREADS_SUBMITTING_WORK);
List<Runnable> runnables = new ArrayList<Runnable>();
final ConcurrentLinkedQueue<TestSubscriber<String>> subscribers = new ConcurrentLinkedQueue<TestSubscriber<String>>();
HystrixRequestContext context = HystrixRequestContext.initializeContext();
final AtomicInteger uniqueInt = new AtomicInteger(0);
for (int i = 0; i < NUM_THREADS_SUBMITTING_WORK; i++) {
runnables.add(new Runnable() {
@Override
public void run() {
try {
for (int j = 0; j < NUM_REQUESTS_PER_THREAD; j++) {
HystrixObservableCollapser<String, String, String, String> collapser = new TestCollapserWithMultipleResponses(timer, uniqueInt.getAndIncrement(), 3, false);
Observable<String> o = collapser.toObservable();
TestSubscriber<String> subscriber = new TestSubscriber<String>();
o.subscribe(subscriber);
subscribers.offer(subscriber);
}
//System.out.println("Runnable done on thread : " + Thread.currentThread().getName());
} finally {
latch.countDown();
}
}
});
}
for (Runnable r : runnables) {
threadPool.submit(new HystrixContextRunnable(r));
}
assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
for (TestSubscriber<String> subscriber : subscribers) {
subscriber.awaitTerminalEvent();
if (subscriber.getOnErrorEvents().size() > 0) {
System.out.println("ERROR : " + subscriber.getOnErrorEvents());
for (Throwable ex : subscriber.getOnErrorEvents()) {
ex.printStackTrace();
}
}
subscriber.assertCompleted();
subscriber.assertNoErrors();
System.out.println("Received : " + subscriber.getOnNextEvents());
subscriber.assertValueCount(3);
}
context.shutdown();
}
use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.
the class HystrixObservableCommandTest method testExecutionSemaphoreWithObserve.
@Test
public void testExecutionSemaphoreWithObserve() {
final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
TestSemaphoreCommand command1 = new TestSemaphoreCommand(circuitBreaker, 1, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
// single thread should work
try {
boolean result = command1.observe().toBlocking().toFuture().get();
assertTrue(result);
} catch (Exception e) {
// we shouldn't fail on this one
throw new RuntimeException(e);
}
final AtomicBoolean exceptionReceived = new AtomicBoolean();
final TryableSemaphoreActual semaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1));
final TestSemaphoreCommand command2 = new TestSemaphoreCommand(circuitBreaker, semaphore, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
try {
command2.observe().toBlocking().toFuture().get();
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
final TestSemaphoreCommand command3 = new TestSemaphoreCommand(circuitBreaker, semaphore, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
Runnable r3 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
try {
command3.observe().toBlocking().toFuture().get();
} catch (Exception e) {
e.printStackTrace();
exceptionReceived.set(true);
}
}
});
// 2 threads, the second should be rejected by the semaphore
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t2.start();
try {
Thread.sleep(100);
} catch (Throwable ex) {
fail(ex.getMessage());
}
t3.start();
try {
t2.join();
t3.join();
} catch (Exception e) {
e.printStackTrace();
fail("failed waiting on threads");
}
if (!exceptionReceived.get()) {
fail("We expected an exception on the 2nd get");
}
System.out.println("CMD1 : " + command1.getExecutionEvents());
System.out.println("CMD2 : " + command2.getExecutionEvents());
System.out.println("CMD3 : " + command3.getExecutionEvents());
assertCommandExecutionEvents(command1, HystrixEventType.EMIT, HystrixEventType.SUCCESS);
assertCommandExecutionEvents(command2, HystrixEventType.EMIT, HystrixEventType.SUCCESS);
assertCommandExecutionEvents(command3, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_MISSING);
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
assertSaneHystrixRequestLog(3);
}
Aggregations