/** * Copyright 2015 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.netflix.hystrix; import com.netflix.hystrix.strategy.HystrixPlugins; import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable; import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableDefault; import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle; import com.netflix.hystrix.strategy.properties.HystrixPropertiesFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.concurrent.Callable; import static org.junit.Assert.*; public class HystrixCommandTestWithCustomConcurrencyStrategy { @Before public void init() { HystrixPlugins.reset(); } @After public void reset() { HystrixRequestContext.setContextOnCurrentThread(null); HystrixPropertiesFactory.reset(); HystrixPlugins.reset(); } /** * HystrixConcurrencyStrategy ** useDefaultRequestContext : true * HystrixCommand ** useRequestCache : true ** useRequestLog : true * * OUTCOME: RequestLog set up properly in command */ @Test public void testCommandRequiresContextConcurrencyStrategyProvidesItContextSetUpCorrectly() { HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(true); HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); //context is set up properly HystrixRequestContext context = HystrixRequestContext.initializeContext(); HystrixCommand<Boolean> cmd = new TestCommand(true, true); assertTrue(cmd.execute()); printRequestLog(); assertNotNull(HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); assertNotNull(cmd.currentRequestLog); context.shutdown(); } /** * HystrixConcurrencyStrategy ** useDefaultRequestContext : true * HystrixCommand ** useRequestCache : true ** useRequestLog : true * * OUTCOME: RequestLog not set up properly in command, static access is null */ @Test public void testCommandRequiresContextConcurrencyStrategyProvidesItContextLeftUninitialized() { HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(true); HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); //context is not set up HystrixRequestContext.setContextOnCurrentThread(null); HystrixCommand<Boolean> cmd = new TestCommand(true, true); assertTrue(cmd.execute()); //command execution not affected by missing context printRequestLog(); assertNull(HystrixRequestLog.getCurrentRequest()); assertNull(HystrixRequestLog.getCurrentRequest(strategy)); assertNull(cmd.currentRequestLog); } /** * HystrixConcurrencyStrategy ** useDefaultRequestContext : false * HystrixCommand ** useRequestCache : true ** useRequestLog : true * * OUTCOME: RequestLog not set up in command, not available statically */ @Test public void testCommandRequiresContextConcurrencyStrategyDoesNotProvideItContextSetUpCorrectly() { 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(); } /** * HystrixConcurrencyStrategy ** useDefaultRequestContext : false * HystrixCommand ** useRequestCache : true ** useRequestLog : true * * OUTCOME: RequestLog not set up in command, not available statically */ @Test public void testCommandRequiresContextConcurrencyStrategyDoesNotProvideItContextLeftUninitialized() { HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(false); HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); //context is not set up HystrixRequestContext.setContextOnCurrentThread(null); HystrixCommand<Boolean> cmd = new TestCommand(true, true); assertTrue(cmd.execute()); //command execution not affected by missing context printRequestLog(); assertNull(HystrixRequestLog.getCurrentRequest()); assertNull(HystrixRequestLog.getCurrentRequest(strategy)); assertNull(cmd.currentRequestLog); } /** * 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(); } /** * HystrixConcurrencyStrategy ** useDefaultRequestContext : true * HystrixCommand ** useRequestCache : false ** useRequestLog : false * * OUTCOME: RequestLog not set up in command, static access is null */ @Test public void testCommandDoesNotRequireContextConcurrencyStrategyProvidesItContextLeftUninitialized() { HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(true); HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); //context is not set up HystrixRequestContext.setContextOnCurrentThread(null); HystrixCommand<Boolean> cmd = new TestCommand(false, false); assertTrue(cmd.execute()); //command execution not affected by missing context printRequestLog(); assertNull(HystrixRequestLog.getCurrentRequest()); assertNull(HystrixRequestLog.getCurrentRequest(strategy)); assertNull(cmd.currentRequestLog); } /** * 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(); } /** * HystrixConcurrencyStrategy ** useDefaultRequestContext : false * HystrixCommand ** useRequestCache : false ** useRequestLog : false * * OUTCOME: RequestLog not set up in command, not available statically */ @Test public void testCommandDoesNotRequireContextConcurrencyStrategyDoesNotProvideItContextLeftUninitialized() { HystrixConcurrencyStrategy strategy = new CustomConcurrencyStrategy(false); HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); //context is not set up HystrixRequestContext.setContextOnCurrentThread(null); HystrixCommand<Boolean> cmd = new TestCommand(true, true); assertTrue(cmd.execute()); //command execution unaffected by missing context printRequestLog(); assertNull(HystrixRequestLog.getCurrentRequest()); assertNull(HystrixRequestLog.getCurrentRequest(strategy)); assertNull(cmd.currentRequestLog); } public static class TestCommand extends HystrixCommand<Boolean> { public TestCommand(boolean cacheEnabled, boolean logEnabled) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("TEST")).andCommandPropertiesDefaults(new HystrixCommandProperties.Setter().withRequestCacheEnabled(cacheEnabled).withRequestLogEnabled(logEnabled))); } @Override protected Boolean run() throws Exception { return true; } } private static void printRequestLog() { HystrixRequestLog currentLog = HystrixRequestLog.getCurrentRequest(); if (currentLog != null) { System.out.println("RequestLog contents : " + currentLog.getExecutedCommandsAsString()); } else { System.out.println("<NULL> HystrixRequestLog"); } } public static class CustomConcurrencyStrategy extends HystrixConcurrencyStrategy { private final boolean useDefaultRequestContext; public CustomConcurrencyStrategy(boolean useDefaultRequestContext) { this.useDefaultRequestContext = useDefaultRequestContext; } @Override public <T> Callable<T> wrapCallable(Callable<T> callable) { return new LoggingCallable<T>(callable); } @Override public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) { if (useDefaultRequestContext) { //this is the default RequestVariable implementation that requires a HystrixRequestContext return super.getRequestVariable(rv); } else { //this ignores the HystrixRequestContext return new HystrixRequestVariableDefault<T>() { @Override public T initialValue() { return null; } @Override public T get() { return null; } @Override public void set(T value) { //do nothing } @Override public void remove() { //do nothing } @Override public void shutdown(T value) { //do nothing } }; } } } public static class LoggingCallable<T> implements Callable<T> { private final Callable<T> callable; public LoggingCallable(Callable<T> callable) { this.callable = callable; } @Override public T call() throws Exception { System.out.println("********start call()"); return callable.call(); } } }