use of com.netflix.hystrix.strategy.concurrency.HystrixRequestContext in project Hystrix by Netflix.
the class HystrixCollapserTest method testRequestVariableLifecycle2.
@Test
public void testRequestVariableLifecycle2() throws Exception {
final HystrixRequestContext reqContext = HystrixRequestContext.initializeContext();
final TestCollapserTimer timer = new TestCollapserTimer();
final ConcurrentLinkedQueue<Future<String>> responses = new ConcurrentLinkedQueue<Future<String>>();
ConcurrentLinkedQueue<Thread> threads = new ConcurrentLinkedQueue<Thread>();
// kick off work (simulating a single request with multiple threads)
for (int t = 0; t < 5; t++) {
final int outerLoop = t;
Thread th = new Thread(new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
int uniqueInt = (outerLoop * 100) + i;
responses.add(new TestRequestCollapser(timer, uniqueInt).queue());
}
}
}));
threads.add(th);
th.start();
}
for (Thread th : threads) {
// wait for each thread to finish
th.join();
}
// we expect 5 threads * 100 responses each
assertEquals(500, responses.size());
for (Future<String> f : responses) {
// they should not be done yet because the counter hasn't incremented
assertFalse(f.isDone());
}
timer.incrementTime(5);
HystrixCollapser<List<String>, String, String> collapser1 = new TestRequestCollapser(timer, 2);
Future<String> response2 = collapser1.queue();
timer.incrementTime(8);
// should execute here
Future<String> response3 = new TestRequestCollapser(timer, 3).queue();
timer.incrementTime(6);
Future<String> response4 = new TestRequestCollapser(timer, 4).queue();
timer.incrementTime(8);
// should execute here
Future<String> response5 = new TestRequestCollapser(timer, 5).queue();
timer.incrementTime(10);
// wait for all tasks to complete
for (Future<String> f : responses) {
f.get(1000, TimeUnit.MILLISECONDS);
}
assertEquals("2", response2.get(1000, TimeUnit.MILLISECONDS));
assertEquals("3", response3.get(1000, TimeUnit.MILLISECONDS));
assertEquals("4", response4.get(1000, TimeUnit.MILLISECONDS));
assertEquals("5", response5.get(1000, TimeUnit.MILLISECONDS));
// each task should have been executed 3 times
for (TestCollapserTimer.ATask t : timer.tasks) {
assertEquals(3, t.task.count.get());
}
Iterator<HystrixInvokableInfo<?>> cmdIterator = HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().iterator();
assertEquals(500, cmdIterator.next().getNumberCollapsed());
assertEquals(2, cmdIterator.next().getNumberCollapsed());
assertEquals(1, cmdIterator.next().getNumberCollapsed());
HystrixRequestVariableHolder<RequestCollapser<?, ?, ?>> rv = RequestCollapserFactory.getRequestVariable(new TestRequestCollapser(timer, 1).getCollapserKey().name());
reqContext.close();
assertNotNull(rv);
// they should have all been removed as part of ThreadContext.remove()
assertEquals(0, timer.tasks.size());
}
use of com.netflix.hystrix.strategy.concurrency.HystrixRequestContext in project Hystrix by Netflix.
the class AbstractCommand method executeCommandAndObserve.
/**
* This decorates "Hystrix" functionality around the run() Observable.
*
* @return R
*/
private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
final Action1<R> markEmits = new Action1<R>() {
@Override
public void call(R r) {
if (shouldOutputOnNextEvents()) {
executionResult = executionResult.addEvent(HystrixEventType.EMIT);
eventNotifier.markEvent(HystrixEventType.EMIT, commandKey);
}
if (commandIsScalar()) {
long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
circuitBreaker.markSuccess();
}
}
};
final Action0 markOnCompleted = new Action0() {
@Override
public void call() {
if (!commandIsScalar()) {
long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
circuitBreaker.markSuccess();
}
}
};
final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() {
@Override
public Observable<R> call(Throwable t) {
Exception e = getExceptionFromThrowable(t);
executionResult = executionResult.setExecutionException(e);
if (e instanceof RejectedExecutionException) {
return handleThreadPoolRejectionViaFallback(e);
} else if (t instanceof HystrixTimeoutException) {
return handleTimeoutViaFallback();
} else if (t instanceof HystrixBadRequestException) {
return handleBadRequestByEmittingError(e);
} else {
/*
* Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.
*/
if (e instanceof HystrixBadRequestException) {
eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
return Observable.error(e);
}
return handleFailureViaFallback(e);
}
}
};
final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() {
@Override
public void call(Notification<? super R> rNotification) {
setRequestContextIfNeeded(currentRequestContext);
}
};
Observable<R> execution;
if (properties.executionTimeoutEnabled().get()) {
execution = executeCommandWithSpecifiedIsolation(_cmd).lift(new HystrixObservableTimeoutOperator<R>(_cmd));
} else {
execution = executeCommandWithSpecifiedIsolation(_cmd);
}
return execution.doOnNext(markEmits).doOnCompleted(markOnCompleted).onErrorResumeNext(handleFallback).doOnEach(setRequestContext);
}
use of com.netflix.hystrix.strategy.concurrency.HystrixRequestContext in project Hystrix by Netflix.
the class HystrixCommandTestWithCustomConcurrencyStrategy method testCommandDoesNotRequireContextConcurrencyStrategyProvidesItContextSetUpCorrectly.
/**
* HystrixConcurrencyStrategy
** useDefaultRequestContext : true
* HystrixCommand
** useRequestCache : false
** useRequestLog : false
*
* OUTCOME: RequestLog not set up in command, static access works properly
*/
@Test
public void testCommandDoesNotRequireContextConcurrencyStrategyProvidesItContextSetUpCorrectly() {
HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(true);
HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy);
//context is set up properly
HystrixRequestContext context = HystrixRequestContext.initializeContext();
HystrixCommand<Boolean> cmd = new TestCommand(false, false);
assertTrue(cmd.execute());
printRequestLog();
assertNotNull(HystrixRequestLog.getCurrentRequest());
assertNotNull(HystrixRequestLog.getCurrentRequest(strategy));
assertNull(cmd.currentRequestLog);
context.shutdown();
}
use of com.netflix.hystrix.strategy.concurrency.HystrixRequestContext in project Hystrix by Netflix.
the class HystrixCommandTestWithCustomConcurrencyStrategy method testCommandDoesNotRequireContextConcurrencyStrategyDoesNotProvideItContextSetUpCorrectly.
/**
* HystrixConcurrencyStrategy
** useDefaultRequestContext : false
* HystrixCommand
** useRequestCache : false
** useRequestLog : false
*
* OUTCOME: RequestLog not set up in command, not available statically
*/
@Test
public void testCommandDoesNotRequireContextConcurrencyStrategyDoesNotProvideItContextSetUpCorrectly() {
HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(false);
HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy);
//context is set up properly
HystrixRequestContext context = HystrixRequestContext.initializeContext();
HystrixCommand<Boolean> cmd = new TestCommand(true, true);
assertTrue(cmd.execute());
printRequestLog();
assertNull(HystrixRequestLog.getCurrentRequest());
assertNull(HystrixRequestLog.getCurrentRequest(strategy));
assertNull(cmd.currentRequestLog);
context.shutdown();
}
use of com.netflix.hystrix.strategy.concurrency.HystrixRequestContext 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();
}
Aggregations