DATAREDIS-414 - Serialization now occurs after pooled connection was released.
Moved key serialization and value deserialization outside of callback so that pooled connections get released more quickly. Original pull request: #153.
This commit is contained in:
committed by
Oliver Gierke
parent
7073502e42
commit
a08e90a1f7
@@ -101,18 +101,17 @@ public class RedisCache implements Cache {
|
||||
public RedisCacheElement get(final RedisCacheKey cacheKey) {
|
||||
|
||||
notNull(cacheKey, "CacheKey must not be null!");
|
||||
return (RedisCacheElement) redisOperations.execute(new AbstractRedisCacheCallback<RedisCacheElement>(
|
||||
new RedisCacheElement(cacheKey, null), cacheMetadata) {
|
||||
|
||||
byte[] bytes = (byte[]) redisOperations.execute(new AbstractRedisCacheCallback<byte[]>(new BinaryRedisCacheElement(
|
||||
new RedisCacheElement(cacheKey, null), cacheValueAccessor), cacheMetadata) {
|
||||
|
||||
@Override
|
||||
public RedisCacheElement doInRedis(RedisCacheElement element, RedisConnection connection)
|
||||
throws DataAccessException {
|
||||
|
||||
byte[] bs = connection.get(element.getKeyBytes());
|
||||
Object value = redisOperations.getValueSerializer() != null ? redisOperations.getValueSerializer().deserialize(bs) : bs;
|
||||
return (bs == null ? null : new RedisCacheElement(element.getKey(), value));
|
||||
public byte[] doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
return connection.get(element.getKeyBytes());
|
||||
}
|
||||
});
|
||||
|
||||
return (bytes == null ? null : new RedisCacheElement(cacheKey, cacheValueAccessor.deserializeIfNecessary(bytes)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -137,7 +136,9 @@ public class RedisCache implements Cache {
|
||||
public void put(RedisCacheElement element) {
|
||||
|
||||
notNull(element, "Element must not be null!");
|
||||
redisOperations.execute(new RedisCachePutCallback(element, cacheValueAccessor, cacheMetadata));
|
||||
|
||||
redisOperations.execute(new RedisCachePutCallback(new BinaryRedisCacheElement(element, cacheValueAccessor),
|
||||
cacheMetadata));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -147,7 +148,8 @@ public class RedisCache implements Cache {
|
||||
public ValueWrapper putIfAbsent(Object key, final Object value) {
|
||||
|
||||
return putIfAbsent(new RedisCacheElement(new RedisCacheKey(key).usePrefix(cacheMetadata.getKeyPrefix())
|
||||
.withKeySerializer(redisOperations.getKeySerializer()), value).expireAfter(cacheMetadata.getDefaultExpiration()));
|
||||
.withKeySerializer(redisOperations.getKeySerializer()), value)
|
||||
.expireAfter(cacheMetadata.getDefaultExpiration()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +163,12 @@ public class RedisCache implements Cache {
|
||||
public ValueWrapper putIfAbsent(RedisCacheElement element) {
|
||||
|
||||
notNull(element, "Element must not be null!");
|
||||
return toWrapper(redisOperations.execute(new RedisCachePutIfAbsentCallback(element, cacheValueAccessor, cacheMetadata)));
|
||||
|
||||
new RedisCachePutIfAbsentCallback(new BinaryRedisCacheElement(element, cacheValueAccessor), cacheMetadata);
|
||||
|
||||
return toWrapper(cacheValueAccessor.deserializeIfNecessary((byte[]) redisOperations
|
||||
.execute(new RedisCachePutIfAbsentCallback(new BinaryRedisCacheElement(element, cacheValueAccessor),
|
||||
cacheMetadata))));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -180,7 +187,8 @@ public class RedisCache implements Cache {
|
||||
public void evict(final RedisCacheElement element) {
|
||||
|
||||
notNull(element, "Element must not be null!");
|
||||
redisOperations.execute(new RedisCacheEvictCallback(element, cacheMetadata));
|
||||
redisOperations.execute(new RedisCacheEvictCallback(new BinaryRedisCacheElement(element, cacheValueAccessor),
|
||||
cacheMetadata));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -323,6 +331,10 @@ public class RedisCache implements Cache {
|
||||
|
||||
byte[] convertToBytesIfNecessary(Object value) {
|
||||
|
||||
if (value == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
if (valueSerializer == null && value instanceof byte[]) {
|
||||
return (byte[]) value;
|
||||
}
|
||||
@@ -340,6 +352,52 @@ public class RedisCache implements Cache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.6
|
||||
*/
|
||||
static class BinaryRedisCacheElement extends RedisCacheElement {
|
||||
|
||||
private byte[] keyBytes;
|
||||
private byte[] valueBytes;
|
||||
private RedisCacheElement element;
|
||||
|
||||
public BinaryRedisCacheElement(RedisCacheElement element, CacheValueAccessor accessor) {
|
||||
|
||||
super(element.getKey(), element.get());
|
||||
this.element = element;
|
||||
this.keyBytes = element.getKeyBytes();
|
||||
this.valueBytes = accessor.convertToBytesIfNecessary(element.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getKeyBytes() {
|
||||
return keyBytes;
|
||||
}
|
||||
|
||||
public long getTimeToLive() {
|
||||
return element.getTimeToLive();
|
||||
}
|
||||
|
||||
public boolean hasKeyPrefix() {
|
||||
return element.hasKeyPrefix();
|
||||
}
|
||||
|
||||
public boolean isEternal() {
|
||||
return element.isEternal();
|
||||
}
|
||||
|
||||
public RedisCacheElement expireAfter(long seconds) {
|
||||
return element.expireAfter(seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] get() {
|
||||
return valueBytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.5
|
||||
@@ -348,10 +406,10 @@ public class RedisCache implements Cache {
|
||||
static abstract class AbstractRedisCacheCallback<T> implements RedisCallback<T> {
|
||||
|
||||
private long WAIT_FOR_LOCK_TIMEOUT = 300;
|
||||
private final RedisCacheElement element;
|
||||
private final BinaryRedisCacheElement element;
|
||||
private final RedisCacheMetadata cacheMetadata;
|
||||
|
||||
public AbstractRedisCacheCallback(RedisCacheElement element, RedisCacheMetadata metadata) {
|
||||
public AbstractRedisCacheCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
|
||||
this.element = element;
|
||||
this.cacheMetadata = metadata;
|
||||
}
|
||||
@@ -366,7 +424,7 @@ public class RedisCache implements Cache {
|
||||
return doInRedis(element, connection);
|
||||
}
|
||||
|
||||
public abstract T doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException;
|
||||
public abstract T doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException;
|
||||
|
||||
protected void processKeyExpiration(RedisCacheElement element, RedisConnection connection) {
|
||||
if (!element.isEternal()) {
|
||||
@@ -526,7 +584,7 @@ public class RedisCache implements Cache {
|
||||
*/
|
||||
static class RedisCacheEvictCallback extends AbstractRedisCacheCallback<Void> {
|
||||
|
||||
public RedisCacheEvictCallback(RedisCacheElement element, RedisCacheMetadata metadata) {
|
||||
public RedisCacheEvictCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
|
||||
super(element, metadata);
|
||||
}
|
||||
|
||||
@@ -535,7 +593,7 @@ public class RedisCache implements Cache {
|
||||
* @see org.springframework.data.redis.cache.RedisCache.AbstractRedisCacheCallback#doInRedis(org.springframework.data.redis.cache.RedisCacheElement, org.springframework.data.redis.connection.RedisConnection)
|
||||
*/
|
||||
@Override
|
||||
public Void doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
public Void doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
|
||||
connection.del(element.getKeyBytes());
|
||||
cleanKnownKeys(element, connection);
|
||||
@@ -549,13 +607,9 @@ public class RedisCache implements Cache {
|
||||
*/
|
||||
static class RedisCachePutCallback extends AbstractRedisCacheCallback<Void> {
|
||||
|
||||
private final CacheValueAccessor valueAccessor;
|
||||
|
||||
public RedisCachePutCallback(RedisCacheElement element, CacheValueAccessor valueAccessor,
|
||||
RedisCacheMetadata metadata) {
|
||||
public RedisCachePutCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
|
||||
|
||||
super(element, metadata);
|
||||
this.valueAccessor = valueAccessor;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -563,11 +617,11 @@ public class RedisCache implements Cache {
|
||||
* @see org.springframework.data.redis.cache.RedisCache.AbstractRedisPutCallback#doInRedis(org.springframework.data.redis.cache.RedisCache.RedisCacheElement, org.springframework.data.redis.connection.RedisConnection)
|
||||
*/
|
||||
@Override
|
||||
public Void doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
public Void doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
|
||||
connection.multi();
|
||||
|
||||
connection.set(element.getKeyBytes(), valueAccessor.convertToBytesIfNecessary(element.get()));
|
||||
connection.set(element.getKeyBytes(), element.get());
|
||||
|
||||
processKeyExpiration(element, connection);
|
||||
maintainKnownKeys(element, connection);
|
||||
@@ -581,15 +635,10 @@ public class RedisCache implements Cache {
|
||||
* @author Christoph Strobl
|
||||
* @since 1.5
|
||||
*/
|
||||
static class RedisCachePutIfAbsentCallback extends AbstractRedisCacheCallback<Object> {
|
||||
|
||||
private final CacheValueAccessor valueAccessor;
|
||||
|
||||
public RedisCachePutIfAbsentCallback(RedisCacheElement element, CacheValueAccessor valueAccessor,
|
||||
RedisCacheMetadata metadata) {
|
||||
static class RedisCachePutIfAbsentCallback extends AbstractRedisCacheCallback<byte[]> {
|
||||
|
||||
public RedisCachePutIfAbsentCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
|
||||
super(element, metadata);
|
||||
this.valueAccessor = valueAccessor;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -597,10 +646,10 @@ public class RedisCache implements Cache {
|
||||
* @see org.springframework.data.redis.cache.RedisCache.AbstractRedisPutCallback#doInRedis(org.springframework.data.redis.cache.RedisCache.RedisCacheElement, org.springframework.data.redis.connection.RedisConnection)
|
||||
*/
|
||||
@Override
|
||||
public Object doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
public byte[] doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
|
||||
waitForLock(connection);
|
||||
Object resultValue = put(element, connection);
|
||||
byte[] resultValue = put(element, connection);
|
||||
|
||||
if (nullSafeEquals(element.get(), resultValue)) {
|
||||
processKeyExpiration(element, connection);
|
||||
@@ -610,11 +659,10 @@ public class RedisCache implements Cache {
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
private Object put(RedisCacheElement element, RedisConnection connection) {
|
||||
private byte[] put(BinaryRedisCacheElement element, RedisConnection connection) {
|
||||
|
||||
boolean valueWasSet = connection.setNX(element.getKeyBytes(),
|
||||
valueAccessor.convertToBytesIfNecessary(element.get()));
|
||||
return valueWasSet ? null : valueAccessor.deserializeIfNecessary(connection.get(element.getKeyBytes()));
|
||||
boolean valueWasSet = connection.setNX(element.getKeyBytes(), element.get());
|
||||
return valueWasSet ? null : connection.get(element.getKeyBytes());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user