Add RedisTemplate executePipelined methods

DATAREDIS-119

Add methods to execute RedisCallbacks and
SessionCallbacks in a pipeline and return
deserialized results
This commit is contained in:
Jennifer Hickey
2013-07-25 15:16:12 -07:00
parent f90e373877
commit a5fc567d4a
3 changed files with 200 additions and 45 deletions

View File

@@ -64,16 +64,45 @@ public interface RedisOperations<K, V> {
*/
<T> T execute(SessionCallback<T> session);
// /**
// * Executes the given action object on a pipelined connection, returning the results. Note that the callback <b>cannot</b>
// * return a non-null value as it gets overwritten by the pipeline.
// *
// * @param <T> list element return type
// * @param action callback object to execute
// * @return list of objects returned by the pipeline
// */
// List<V> executePipelined(RedisCallback<?> action);
/**
* Executes the given action object on a pipelined connection, returning the results. Note that the callback <b>cannot</b>
* return a non-null value as it gets overwritten by the pipeline.
*
* This method will use the default serializers to deserialize results
*
* @param action callback object to execute
* @return list of objects returned by the pipeline
*/
List<Object> executePipelined(RedisCallback<?> action);
/**
* Executes the given action object on a pipelined connection, returning the results using a dedicated serializer.
* Note that the callback <b>cannot</b> return a non-null value as it gets overwritten by the pipeline.
*
* @param action callback object to execute
* @param resultSerializer The Serializer to use for individual values or Collections of values. If any
* returned values are hashes, this serializer will be used to deserialize both the key and value
* @return list of objects returned by the pipeline
*/
List<Object> executePipelined(final RedisCallback<?> action, final RedisSerializer<?> resultSerializer);
/**
* Executes the given Redis session on a pipelined connection. Allows transactions to be pipelined.
* Note that the callback <b>cannot</b> return a non-null value as it gets overwritten by the pipeline.
* @param session Session callback
* @return list of objects returned by the pipeline
*/
List<Object> executePipelined(final SessionCallback<?> session);
/**
* Executes the given Redis session on a pipelined connection, returning the results using a dedicated serializer.
* Allows transactions to be pipelined.
* Note that the callback <b>cannot</b> return a non-null value as it gets overwritten by the pipeline.
* @param session Session callback
* @param resultSerializer
* @return list of objects returned by the pipeline
*/
List<Object> executePipelined(final SessionCallback<?> session, final RedisSerializer<?> resultSerializer);
Boolean hasKey(K key);

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnection;
@@ -201,42 +202,75 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
}
// @SuppressWarnings("unchecked")
// public List<V> executePipelined(final RedisCallback<?> action) {
// return executePipelined(action, valueSerializer);
// }
//
// /**
// * Executes the given action object on a pipelined connection, returning the results using a dedicated serializer.
// * Note that the callback <b>cannot</b> return a non-null value as it gets overwritten by the pipeline.
// *
// * @param action callback object to execute
// * @param resultSerializer
// * @return list of objects returned by the pipeline
// */
// public <T> List<T> executePipelined(final RedisCallback<?> action, final RedisSerializer<T> resultSerializer) {
// return execute(new RedisCallback<List<T>>() {
// public List<T> doInRedis(RedisConnection connection) throws DataAccessException {
// connection.openPipeline();
// boolean pipelinedClosed = false;
// try {
// Object result = action.doInRedis(connection);
// if (result != null) {
// throw new InvalidDataAccessApiUsageException(
// "Callback cannot returned a non-null value as it gets overwritten by the pipeline");
// }
// List<Object> closePipeline = connection.closePipeline();
// pipelinedClosed = true;
// //return SerializationUtils.deserialize(pipeline, resultSerializer);
//
// } finally {
// if (!pipelinedClosed) {
// connection.closePipeline();
// }
// }
// }
// });
// }
public List<Object> executePipelined(final SessionCallback<?> session) {
return executePipelined(session, valueSerializer);
}
public List<Object> executePipelined(final SessionCallback<?> session, final RedisSerializer<?> resultSerializer) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory);
try {
return execute(new RedisCallback<List<Object>>() {
public List<Object> doInRedis(RedisConnection connection) throws DataAccessException {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = executeSession(session);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer,
hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
}
});
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
public List<Object> executePipelined(final RedisCallback<?> action) {
return executePipelined(action, valueSerializer);
}
public List<Object> executePipelined(final RedisCallback<?> action, final RedisSerializer<?> resultSerializer) {
return execute(new RedisCallback<List<Object>>() {
public List<Object> doInRedis(RedisConnection connection) throws DataAccessException {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = action.doInRedis(connection);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer,
resultSerializer, resultSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
}
});
}
private Object executeSession(SessionCallback<?> session) {
return session.execute(this);
}
protected RedisConnection createRedisConnectionProxy(RedisConnection pm) {
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(), getClass().getClassLoader());