Skip to content

Commit

Permalink
Merge pull request #347 from sawano/master
Browse files Browse the repository at this point in the history
Allow for @HystrixCommand to be used on parameterized return type
  • Loading branch information
benjchristensen committed Dec 11, 2014
2 parents ad3ed06 + 2137cb1 commit 20b81dc
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,15 @@ public enum ExecutionType {
*/
OBSERVABLE;


/**
* Gets execution type for specified class type.
* @param type the type
* @return the execution type {@link ExecutionType}
*/
public static ExecutionType getExecutionType(Class<?> type) {
if (type.isAssignableFrom(Future.class)) {
if (Future.class.isAssignableFrom(type)) {
return ExecutionType.ASYNCHRONOUS;
} else if (type.isAssignableFrom(Observable.class)) {
} else if (Observable.class.isAssignableFrom(type)) {
return ExecutionType.OBSERVABLE;
} else {
return ExecutionType.SYNCHRONOUS;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.netflix.hystrix.contrib.javanica.command;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import rx.Observable;
import rx.internal.operators.OperatorMulticast;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableFuture;

import static com.netflix.hystrix.contrib.javanica.command.ExecutionType.ASYNCHRONOUS;
import static com.netflix.hystrix.contrib.javanica.command.ExecutionType.OBSERVABLE;
import static com.netflix.hystrix.contrib.javanica.command.ExecutionType.SYNCHRONOUS;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class ExecutionTypeTest {

@Parameterized.Parameters
public static List<Object[]> data() {
return asList(new Object[][]{
{returnType(Integer.class), shouldHaveExecutionType(SYNCHRONOUS)},
{returnType(List.class), shouldHaveExecutionType(SYNCHRONOUS)},
{returnType(Object.class), shouldHaveExecutionType(SYNCHRONOUS)},
{returnType(Class.class), shouldHaveExecutionType(SYNCHRONOUS)},
{returnType(Future.class), shouldHaveExecutionType(ASYNCHRONOUS)},
{returnType(AsyncResult.class), shouldHaveExecutionType(ASYNCHRONOUS)},
{returnType(RunnableFuture.class), shouldHaveExecutionType(ASYNCHRONOUS)},
{returnType(CompletableFuture.class), shouldHaveExecutionType(ASYNCHRONOUS)},
{returnType(Observable.class), shouldHaveExecutionType(OBSERVABLE)},
{returnType(OperatorMulticast.class), shouldHaveExecutionType(OBSERVABLE)},
});
}

@Test
public void should_return_correct_execution_type() throws Exception {
assertEquals("Unexpected execution type for method return type: " + methodReturnType, expectedType, ExecutionType.getExecutionType(methodReturnType));

}

private static ExecutionType shouldHaveExecutionType(final ExecutionType type) {
return type;
}

private static Class<?> returnType(final Class<?> aClass) {
return aClass;
}

private final Class<?> methodReturnType;
private final ExecutionType expectedType;

public ExecutionTypeTest(final Class<?> methodReturnType, final ExecutionType expectedType) {
this.methodReturnType = methodReturnType;
this.expectedType = expectedType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import com.netflix.hystrix.contrib.javanica.test.spring.conf.AopCglibConfig;
import com.netflix.hystrix.contrib.javanica.test.spring.domain.User;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -34,46 +36,57 @@ public class CommandTest {

@Autowired
private UserService userService;
private HystrixRequestContext context;

@Before
public void setUp() throws Exception {
context = HystrixRequestContext.initializeContext();
}

@After
public void tearDown() throws Exception {
context.shutdown();
}

@Test
public void testGetUserAsync() throws ExecutionException, InterruptedException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
Future<User> f1 = userService.getUserAsync("1", "name: ");

assertEquals("name: 1", f1.get().getName());
assertEquals(1, HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().size());
com.netflix.hystrix.HystrixExecutableInfo<?> command = HystrixRequestLog.getCurrentRequest()
.getAllExecutedCommands().iterator().next();
// assert the command key name is the we're expecting
assertEquals("GetUserCommand", command.getCommandKey().name());
// assert the command group key name is the we're expecting
assertEquals("UserService", command.getCommandGroup().name());
// assert the command thread pool key name is the we're expecting
assertEquals("CommandTestAsync", command.getThreadPoolKey().name());
// it was successful
assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS));
} finally {
context.shutdown();
}
Future<User> f1 = userService.getUserAsync("1", "name: ");

assertEquals("name: 1", f1.get().getName());
assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size());
com.netflix.hystrix.HystrixCommand<?> command = getCommand();
// assert the command key name is the we're expecting
assertEquals("GetUserCommand", command.getCommandKey().name());
// assert the command group key name is the we're expecting
assertEquals("UserService", command.getCommandGroup().name());
// assert the command thread pool key name is the we're expecting
assertEquals("CommandTestAsync", command.getThreadPoolKey().name());
// it was successful
assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS));
}

@Test
public void testGetUserSync() {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
User u1 = userService.getUserSync("1", "name: ");
assertEquals("name: 1", u1.getName());
assertEquals(1, HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().size());
com.netflix.hystrix.HystrixExecutableInfo<?> command = HystrixRequestLog.getCurrentRequest()
.getAllExecutedCommands().iterator().next();
assertEquals("getUserSync", command.getCommandKey().name());
assertEquals("UserGroup", command.getCommandGroup().name());
assertEquals("UserGroup", command.getThreadPoolKey().name());
assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS));
} finally {
context.shutdown();
}
User u1 = userService.getUserSync("1", "name: ");
assertEquals("name: 1", u1.getName());
assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size());
com.netflix.hystrix.HystrixCommand<?> command = getCommand();
assertEquals("getUserSync", command.getCommandKey().name());
assertEquals("UserGroup", command.getCommandGroup().name());
assertEquals("UserGroup", command.getThreadPoolKey().name());
assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS));
}

@Test
public void should_work_with_parameterized_method() throws Exception {
assertEquals(Integer.valueOf(1), userService.echo(1));

assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size());
assertTrue(getCommand().getExecutionEvents().contains(HystrixEventType.SUCCESS));
}

private com.netflix.hystrix.HystrixCommand<?> getCommand() {
return HystrixRequestLog.getCurrentRequest().getExecutedCommands().iterator().next();
}

public static class UserService {
Expand All @@ -93,6 +106,11 @@ public User getUserSync(String id, String name) {
return new User(id, name + id); // it should be network call
}

@HystrixCommand
public <T> T echo(T value) {
return value;
}

}

@Configurable
Expand Down

0 comments on commit 20b81dc

Please sign in to comment.