Skip to content

Commit

Permalink
Renamed remained recovery to fallback (ReactiveX#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
lespinsideg authored and RobWin committed Oct 28, 2019
1 parent 178bc8d commit 5c8f25d
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedF
if (throwable != null) {
try {
((CompletionStage) fallbackMethod.fallback((Throwable) throwable))
.whenComplete((recoveryResult, recoveryThrowable) -> {
if (recoveryThrowable != null) {
promise.completeExceptionally((Throwable) recoveryThrowable);
.whenComplete((fallbackResult, fallbackThrowable) -> {
if (fallbackThrowable != null) {
promise.completeExceptionally((Throwable) fallbackThrowable);
} else {
promise.complete(recoveryResult);
promise.complete(fallbackResult);
}
});
} catch (Throwable recoveryThrowable) {
promise.completeExceptionally(recoveryThrowable);
} catch (Throwable fallbackThrowable) {
promise.completeExceptionally(fallbackThrowable);
}
} else {
promise.complete(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ public boolean supports(Class<?> target) {
}

@Override
public CheckedFunction0<Object> decorate(FallbackMethod recoveryMethod, CheckedFunction0<Object> supplier) {
public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier) {
return () -> {
try {
return supplier.apply();
} catch (Throwable throwable) {
return recoveryMethod.fallback(throwable);
return fallbackMethod.fallback(throwable);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public interface FallbackDecorator {
boolean supports(Class<?> target);

/**
* @param recoveryMethod fallbackMethod method.
* @param fallbackMethod fallback method.
* @param supplier target function should be decorated.
* @return decorated function
*/
CheckedFunction0<Object> decorate(FallbackMethod recoveryMethod, CheckedFunction0<Object> supplier);
CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@
* {@link FallbackDecorator} resolver
*/
public class FallbackDecorators {
private final List<FallbackDecorator> recoveryDecorator;
private final FallbackDecorator defaultRecoveryDecorator = new DefaultFallbackDecorator();
private final List<FallbackDecorator> fallbackDecorators;
private final FallbackDecorator defaultFallbackDecorator = new DefaultFallbackDecorator();

public FallbackDecorators(List<FallbackDecorator> recoveryDecorator) {
this.recoveryDecorator = recoveryDecorator;
public FallbackDecorators(List<FallbackDecorator> fallbackDecorators) {
this.fallbackDecorators = fallbackDecorators;
}

/**
* find a {@link FallbackDecorator} by return type of the {@link FallbackMethod} and decorate supplier
*
* @param recoveryMethod fallbackMethod method that handles supplier's exception
* @param fallbackMethod fallback method that handles supplier's exception
* @param supplier original function
* @return a function which is decorated by a {@link FallbackMethod}
*/
public CheckedFunction0<Object> decorate(FallbackMethod recoveryMethod, CheckedFunction0<Object> supplier) {
return get(recoveryMethod.getReturnType())
.decorate(recoveryMethod, supplier);
public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier) {
return get(fallbackMethod.getReturnType())
.decorate(fallbackMethod, supplier);
}

private FallbackDecorator get(Class<?> returnType) {
return recoveryDecorator.stream().filter(it -> it.supports(returnType))
return fallbackDecorators.stream().filter(it -> it.supports(returnType))
.findFirst()
.orElse(defaultRecoveryDecorator);
.orElse(defaultFallbackDecorator);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,33 @@
* </pre>
*/
public class FallbackMethod {
private static final Map<MethodMeta, Map<Class<?>, Method>> RECOVERY_METHODS_CACHE = new ConcurrentReferenceHashMap<>();
private final Map<Class<?>, Method> recoveryMethods;
private static final Map<MethodMeta, Map<Class<?>, Method>> FALLBACK_METHODS_CACHE = new ConcurrentReferenceHashMap<>();
private final Map<Class<?>, Method> fallbackMethods;
private final Object[] args;
private final Object target;
private final Class<?> returnType;

/**
* create a fallbackMethod method.
*
* @param recoveryMethods configured and found recovery methods for this invocation
* @param fallbackMethods configured and found fallback methods for this invocation
* @param originalMethodReturnType the return type of the original source method
* @param args arguments those were passed to the original method. They will be passed to the fallbackMethod method.
* @param target target object the fallbackMethod method will be invoked
*/
private FallbackMethod(Map<Class<?>, Method> recoveryMethods, Class<?> originalMethodReturnType, Object[] args, Object target) {
private FallbackMethod(Map<Class<?>, Method> fallbackMethods, Class<?> originalMethodReturnType, Object[] args, Object target) {

this.recoveryMethods = recoveryMethods;
this.fallbackMethods = fallbackMethods;
this.args = args;
this.target = target;
this.returnType = originalMethodReturnType;
}

/**
* @param fallbackMethodName the configured recovery method name
* @param fallbackMethodName the configured fallback method name
* @param originalMethod the original method which has fallback method configured
* @param args the original method arguments
* @param target the target class that own the original method and recovery method
* @param target the target class that own the original method and fallback method
* @return FallbackMethod instance
*/
public static FallbackMethod create(String fallbackMethodName, Method originalMethod, Object[] args, Object target) throws NoSuchMethodException {
Expand All @@ -77,13 +77,13 @@ public static FallbackMethod create(String fallbackMethodName, Method originalMe
originalMethod.getReturnType(),
target.getClass());

Map<Class<?>, Method> methods = RECOVERY_METHODS_CACHE.computeIfAbsent(methodMeta, FallbackMethod::extractMethods);
Map<Class<?>, Method> methods = FALLBACK_METHODS_CACHE.computeIfAbsent(methodMeta, FallbackMethod::extractMethods);

if (!methods.isEmpty()) {
return new FallbackMethod(methods, originalMethod.getReturnType(), args, target);
} else {
throw new NoSuchMethodException(String.format("%s %s.%s(%s,%s)",
methodMeta.returnType, methodMeta.targetClass, methodMeta.recoveryMethodName,
methodMeta.returnType, methodMeta.targetClass, methodMeta.fallbackMethodName,
StringUtils.arrayToDelimitedString(methodMeta.params, ","), Throwable.class));
}
}
Expand All @@ -92,29 +92,29 @@ public static FallbackMethod create(String fallbackMethodName, Method originalMe
* try to fallback from {@link Throwable}
*
* @param thrown {@link Throwable} that should be fallback
* @return recovered value
* @return fallback value
* @throws Throwable if throwable is unrecoverable, throwable will be thrown
*/
@Nullable
public Object fallback(Throwable thrown) throws Throwable {
if (recoveryMethods.size() == 1) {
Map.Entry<Class<?>, Method> entry = recoveryMethods.entrySet().iterator().next();
if (fallbackMethods.size() == 1) {
Map.Entry<Class<?>, Method> entry = fallbackMethods.entrySet().iterator().next();
if (entry.getKey().isAssignableFrom(thrown.getClass())) {
return invoke(entry.getValue(), thrown);
} else {
throw thrown;
}
}

Method recovery = null;
Method fallback = null;
Class<?> thrownClass = thrown.getClass();
while (recovery == null && thrownClass != Object.class) {
recovery = recoveryMethods.get(thrownClass);
while (fallback == null && thrownClass != Object.class) {
fallback = fallbackMethods.get(thrownClass);
thrownClass = thrownClass.getSuperclass();
}

if (recovery != null) {
return invoke(recovery, thrown);
if (fallback != null) {
return invoke(fallback, thrown);
} else {
throw thrown;
}
Expand Down Expand Up @@ -182,8 +182,8 @@ private static Map<Class<?>, Method> extractMethods(MethodMeta methodMeta) {
}

private static void merge(Method method, Map<Class<?>, Method> methods) {
Class<?>[] recoveryParams = method.getParameterTypes();
Class<?> exception = recoveryParams[recoveryParams.length - 1];
Class<?>[] fallbackParams = method.getParameterTypes();
Class<?> exception = fallbackParams[fallbackParams.length - 1];
Method similar = methods.get(exception);
if (similar == null || Arrays.equals(similar.getParameterTypes(), method.getParameterTypes())) {
methods.put(exception, method);
Expand All @@ -193,7 +193,7 @@ private static void merge(Method method, Map<Class<?>, Method> methods) {
}

private static boolean filter(Method method, MethodMeta methodMeta) {
if (!method.getName().equals(methodMeta.recoveryMethodName)) {
if (!method.getName().equals(methodMeta.fallbackMethodName)) {
return false;
}
if (!methodMeta.returnType.isAssignableFrom(method.getReturnType())) {
Expand All @@ -215,19 +215,19 @@ private static boolean filter(Method method, MethodMeta methodMeta) {
}

private static class MethodMeta {
final String recoveryMethodName;
final String fallbackMethodName;
final Class<?>[] params;
final Class<?> returnType;
final Class<?> targetClass;

/**
* @param recoveryMethodName the configured recovery method name
* @param fallbackMethodName the configured fallback method name
* @param returnType the original method return type
* @param params the original method arguments
* @param targetClass the target class that own the original method and recovery method
* @param targetClass the target class that own the original method and fallback method
*/
MethodMeta(String recoveryMethodName, Class<?>[] params, Class<?> returnType, Class<?> targetClass) {
this.recoveryMethodName = recoveryMethodName;
MethodMeta(String fallbackMethodName, Class<?>[] params, Class<?> returnType, Class<?> targetClass) {
this.fallbackMethodName = fallbackMethodName;
this.params = params;
this.returnType = returnType;
this.targetClass = targetClass;
Expand All @@ -239,14 +239,14 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
MethodMeta that = (MethodMeta) o;
return targetClass.equals(that.targetClass) &&
recoveryMethodName.equals(that.recoveryMethodName) &&
fallbackMethodName.equals(that.fallbackMethodName) &&
returnType.equals(that.returnType) &&
Arrays.equals(params, that.params);
}

@Override
public int hashCode() {
return targetClass.getName().hashCode() ^ recoveryMethodName.hashCode();
return targetClass.getName().hashCode() ^ fallbackMethodName.hashCode();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedF
}

@SuppressWarnings("unchecked")
private <T> Function<? super Throwable, ? extends Publisher<? extends T>> reactorOnErrorResume(FallbackMethod recoveryMethod, Function<? super Throwable, ? extends Publisher<? extends T>> errorFunction) {
private <T> Function<? super Throwable, ? extends Publisher<? extends T>> reactorOnErrorResume(FallbackMethod fallbackMethod, Function<? super Throwable, ? extends Publisher<? extends T>> errorFunction) {
return throwable -> {
try {
return (Publisher<? extends T>) recoveryMethod.fallback(throwable);
} catch (Throwable recoverThrowable) {
return errorFunction.apply(recoverThrowable);
return (Publisher<? extends T>) fallbackMethod.fallback(throwable);
} catch (Throwable fallbackThrowable) {
return errorFunction.apply(fallbackThrowable);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedF
}

@SuppressWarnings("unchecked")
private <T> io.reactivex.functions.Function<Throwable, T> rxJava2OnErrorResumeNext(FallbackMethod recoveryMethod, Function<? super Throwable, ? extends T> errorFunction) {
private <T> io.reactivex.functions.Function<Throwable, T> rxJava2OnErrorResumeNext(FallbackMethod fallbackMethod, Function<? super Throwable, ? extends T> errorFunction) {
return throwable -> {
try {
return (T) recoveryMethod.fallback(throwable);
} catch (Throwable recoverThrowable) {
return (T) errorFunction.apply(recoverThrowable);
return (T) fallbackMethod.fallback(throwable);
} catch (Throwable fallbackThrowable) {
return (T) errorFunction.apply(fallbackThrowable);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public FallbackDecorator completionStageFallbackDecorator() {
}

@Bean
public FallbackDecorators fallbackDecorators(List<FallbackDecorator> recoveryDecorator) {
return new FallbackDecorators(recoveryDecorator);
public FallbackDecorators fallbackDecorators(List<FallbackDecorator> fallbackDecorator) {
return new FallbackDecorators(fallbackDecorator);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,37 +71,37 @@ public String ambiguousFallback(String parameter, IOException exception) {
}

@Test
public void recoverIgnoringParentMethod() throws Throwable {
public void fallbackIgnoringParentMethod() throws Throwable {
Proxy target = new Proxy();
Method testMethod = target.getClass().getMethod("testMethod", String.class);

FallbackMethod recoveryMethod = FallbackMethod.create("fallbackParent", testMethod, new Object[]{"test"}, target);
FallbackMethod fallbackMethod = FallbackMethod.create("fallbackParent", testMethod, new Object[]{"test"}, target);

assertThat(recoveryMethod.fallback(new IllegalStateException("err"))).isEqualTo("proxy-recovered");
assertThat(fallbackMethod.fallback(new IllegalStateException("err"))).isEqualTo("proxy-recovered");
}

@Test
public void recoverIgnoringInterfaceMethod() throws Throwable {
public void fallbackIgnoringInterfaceMethod() throws Throwable {
Proxy target = new Proxy();
Method testMethod = target.getClass().getMethod("testMethod", String.class);

FallbackMethod recoveryMethod = FallbackMethod.create("fallbackInterface", testMethod, new Object[]{"test"}, target);
FallbackMethod fallbackMethod = FallbackMethod.create("fallbackInterface", testMethod, new Object[]{"test"}, target);

assertThat(recoveryMethod.fallback(new IllegalArgumentException("err"))).isEqualTo("proxy-recovered");
assertThat(fallbackMethod.fallback(new IllegalArgumentException("err"))).isEqualTo("proxy-recovered");
}

@Test
public void recoverNotIgnoringInterfaceMethod() throws Throwable {
public void fallbackNotIgnoringInterfaceMethod() throws Throwable {
Proxy target = new Proxy();
Method testMethod = target.getClass().getMethod("testMethod", String.class);

FallbackMethod recoveryMethod = FallbackMethod.create("fallbackOnlyInterface", testMethod, new Object[]{"test"}, target);
FallbackMethod fallbackMethod = FallbackMethod.create("fallbackOnlyInterface", testMethod, new Object[]{"test"}, target);

assertThat(recoveryMethod.fallback(new IllegalArgumentException("err"))).isEqualTo("only-interface-recovered");
assertThat(fallbackMethod.fallback(new IllegalArgumentException("err"))).isEqualTo("only-interface-recovered");
}

@Test
public void dontRecoverAmbiguousMethod() throws Throwable {
public void dontFallbackAmbiguousMethod() throws Throwable {
Proxy target = new Proxy();
Method testMethod = target.getClass().getMethod("testMethod", String.class);

Expand Down
Loading

0 comments on commit 5c8f25d

Please sign in to comment.