package com.lambdaworks.redis; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import com.lambdaworks.redis.api.StatefulConnection; import com.lambdaworks.redis.api.StatefulRedisConnection; import com.lambdaworks.redis.internal.AbstractInvocationHandler; /** * Invocation-handler to synchronize API calls which use Futures as backend. This class leverages the need to implement a full * sync class which just delegates every request. * * @param <K> Key type. * @param <V> Value type. * @author Mark Paluch * @since 3.0 */ class FutureSyncInvocationHandler<K, V> extends AbstractInvocationHandler { private final StatefulConnection<?, ?> connection; private final Object asyncApi; private final MethodTranslator translator; public FutureSyncInvocationHandler(StatefulConnection<?, ?> connection, Object asyncApi, Class<?>[] interfaces) { this.connection = connection; this.asyncApi = asyncApi; this.translator = new MethodTranslator(asyncApi.getClass(), interfaces); } @Override @SuppressWarnings("unchecked") protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable { try { Method targetMethod = this.translator.get(method); Object result = targetMethod.invoke(asyncApi, args); if (result instanceof RedisFuture) { RedisFuture<?> command = (RedisFuture<?>) result; if (!method.getName().equals("exec") && !method.getName().equals("multi")) { if (connection instanceof StatefulRedisConnection && ((StatefulRedisConnection) connection).isMulti()) { return null; } } LettuceFutures.awaitOrCancel(command, connection.getTimeout(), connection.getTimeoutUnit()); return command.get(); } return result; } catch (InvocationTargetException e) { throw e.getTargetException(); } } }