DATAREDIS-468 - Guard multi/exec bocks in RedisCache to allow usage with cluster.
We now guard multi/exec blocks by checking the connection type. This allows to skip those commands when running in cluster. Original pull request: #173.
This commit is contained in:
committed by
Mark Paluch
parent
02742e3b49
commit
7024ef33e0
@@ -28,6 +28,7 @@ import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
import org.springframework.data.redis.connection.RedisClusterConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.ReturnType;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
@@ -670,14 +671,18 @@ public class RedisCache implements Cache {
|
||||
@Override
|
||||
public Void doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
|
||||
|
||||
connection.multi();
|
||||
if (!isClusterConnection(connection)) {
|
||||
connection.multi();
|
||||
}
|
||||
|
||||
connection.set(element.getKeyBytes(), element.get());
|
||||
|
||||
processKeyExpiration(element, connection);
|
||||
maintainKnownKeys(element, connection);
|
||||
|
||||
connection.exec();
|
||||
if (!isClusterConnection(connection)) {
|
||||
connection.exec();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -742,8 +747,11 @@ public class RedisCache implements Cache {
|
||||
return value;
|
||||
}
|
||||
|
||||
connection.watch(element.getKeyBytes());
|
||||
connection.multi();
|
||||
if (!isClusterConnection(connection)) {
|
||||
|
||||
connection.watch(element.getKeyBytes());
|
||||
connection.multi();
|
||||
}
|
||||
|
||||
value = element.get();
|
||||
connection.set(element.getKeyBytes(), value);
|
||||
@@ -751,7 +759,9 @@ public class RedisCache implements Cache {
|
||||
processKeyExpiration(element, connection);
|
||||
maintainKnownKeys(element, connection);
|
||||
|
||||
connection.exec();
|
||||
if (!isClusterConnection(connection)) {
|
||||
connection.exec();
|
||||
}
|
||||
|
||||
return value;
|
||||
} catch (RuntimeException e) {
|
||||
@@ -799,4 +809,8 @@ public class RedisCache implements Cache {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isClusterConnection(RedisConnection connection) {
|
||||
return connection instanceof RedisClusterConnection;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
import org.springframework.data.redis.connection.RedisClusterConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.ReturnType;
|
||||
@@ -217,4 +218,52 @@ public class RedisCacheUnitTests {
|
||||
verifyZeroInteractions(callableMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-468
|
||||
*/
|
||||
@Test
|
||||
public void noMultiExecForCluster() {
|
||||
|
||||
RedisClusterConnection clusterConnectionMock = mock(RedisClusterConnection.class);
|
||||
when(connectionFactoryMock.getConnection()).thenReturn(clusterConnectionMock);
|
||||
|
||||
cache = new RedisCache(CACHE_NAME, NO_PREFIX_BYTES, templateSpy, 0L);
|
||||
|
||||
when(connectionMock.exists(KEY_BYTES)).thenReturn(true);
|
||||
when(connectionMock.get(KEY_BYTES)).thenReturn(null).thenReturn(VALUE_BYTES);
|
||||
|
||||
cache.put(KEY, VALUE);
|
||||
|
||||
verify(clusterConnectionMock, times(1)).set(eq(KEY_BYTES), eq(VALUE_BYTES));
|
||||
verify(clusterConnectionMock, never()).multi();
|
||||
verify(clusterConnectionMock, never()).exec();
|
||||
verifyZeroInteractions(connectionMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-468
|
||||
*/
|
||||
@Test
|
||||
public void getWithCallableForCluster() {
|
||||
|
||||
RedisClusterConnection clusterConnectionMock = mock(RedisClusterConnection.class);
|
||||
when(connectionFactoryMock.getConnection()).thenReturn(clusterConnectionMock);
|
||||
|
||||
cache = new RedisCache(CACHE_NAME, NO_PREFIX_BYTES, templateSpy, 0L);
|
||||
|
||||
cache.get(KEY, new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
return VALUE;
|
||||
}
|
||||
});
|
||||
|
||||
verify(clusterConnectionMock, times(2)).get(eq(KEY_BYTES));
|
||||
verify(clusterConnectionMock, times(1)).set(eq(KEY_BYTES), eq(VALUE_BYTES));
|
||||
|
||||
verify(clusterConnectionMock, never()).multi();
|
||||
verify(clusterConnectionMock, never()).exec();
|
||||
verifyZeroInteractions(connectionMock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user