Package halfpipe.client

Source Code of halfpipe.client.HystrixInvocationHandler$Factory

package halfpipe.client;

import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommand.Setter;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixExecutable;
import feign.InvocationHandlerFactory;
import feign.InvocationHandlerFactory.MethodHandler;
import feign.Target;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.Future;

import static feign.Util.*;
import static halfpipe.util.BeanUtils.*;

/**
* User: spencergibb
* Date: 4/11/14
* Time: 10:44 PM
*/
public class HystrixInvocationHandler implements InvocationHandler {
    private static Logger LOG = LoggerFactory.getLogger(HystrixInvocationHandler.class);

    public static class Factory implements InvocationHandlerFactory {
        @Override
        public InvocationHandler create(Target target, Map<Method, MethodHandler> methodToHandler) {
            return new HystrixInvocationHandler(target, methodToHandler);
        }
    }

    private final Target target;
    private final Map<Method, MethodHandler> methodToHandler;

    public HystrixInvocationHandler(Target target, Map<Method, MethodHandler> methodToHandler) {
        this.target = checkNotNull(target, "target");
        this.methodToHandler = checkNotNull(methodToHandler, "methodToHandler for %s", target);
    }

    @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("equals".equals(method.getName())) {
            try {
                Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                return equals(otherHandler);
            } catch (IllegalArgumentException e) {
                return false;
            }
        }
        if ("hashCode".equals(method.getName())) {
            return hashCode();
        }

        String fallbackBeanName = getBeanName(method, "fallback");
        String setterBeanName = getBeanName(method, "setter");

        String groupKey = context().getEnvironment().getProperty("application.id"); //.optional().or("default");

        Optional<Setter> setterOptional = getOptionalBean(setterBeanName, Setter.class);

        Setter setter = setterOptional.or(Setter
                        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                        .andCommandKey(HystrixCommandKey.Factory.asKey(method.getName()))
        );

        //TODO: support for java 8 Supplier
        Optional<Supplier> fallback = getOptionalBean(fallbackBeanName, Supplier.class);

        MethodHandler methodHandler = methodToHandler.get(method);

        String name = groupKey + ":" + method.getName();
        ProxiedCommand command = new ProxiedCommand(name, setter, methodHandler, args, fallback);

        Class<?> returnType = method.getReturnType();

        if (Future.class.isAssignableFrom(returnType)) {
            return command.queue();
        } else if (Observable.class.isAssignableFrom(returnType)) {
            return command.observe();
        } else if (HystrixExecutable.class.isAssignableFrom(returnType)) {
            return command;
        }

        return command.execute();
    }

    private String getBeanName(Method method, String suffix) {
        String typeName = target.type().getSimpleName();
        return typeName + "." + method.getName() + "."+ suffix;
    }

    @Override public int hashCode() {
        return target.hashCode();
    }

    @Override public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (HystrixInvocationHandler.class != obj.getClass()) {
            return false;
        }
        HystrixInvocationHandler that = HystrixInvocationHandler.class.cast(obj);
        return this.target.equals(that.target);
    }

    @Override public String toString() {
        return "target(" + target + ")";
    }

    public class ProxiedCommand extends HystrixCommand<Object> {

        private final String name;
        private final MethodHandler methodHandler;
        private final Object[] args;
        private final Optional<Supplier> fallback;

        protected ProxiedCommand(String name, Setter setter, MethodHandler methodHandler, Object[] args, Optional<Supplier> fallback) {
            super(setter);
            this.name = name;
            this.methodHandler = methodHandler;
            this.args = args;
            this.fallback = fallback;
        }

        @Override
        protected Object run() throws Exception {
            try {
                return methodHandler.invoke(args);
            } catch (Exception e) {
                throw e;
            } catch (Throwable t) {
                throw new Exception(t);
            }
        }

        @Override
        protected Object getFallback() {
            if (fallback.isPresent()) {
                Supplier supplier = fallback.get();
                return supplier.get();
            }
            Throwable e = getFailedExecutionException();
            LOG.debug("No fallback with exception", e);
            throw new UnsupportedOperationException("No fallback available for "+name, e);
        }
    }
}
TOP

Related Classes of halfpipe.client.HystrixInvocationHandler$Factory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.