DATAREDIS-184 - Add support for 'SAVE/NOSAVE' to shutdown.
Created and added 'ShutdownOptions' to 'RedisServerCommands'. The full implementation is available for 'lettuce' and 'srp'. When using 'jedis' the command is emulated using lua script via 'eval'. For 'jredis' the method is not available and will throw 'UnsupportedOperationException'. Original Pull Request: #47
This commit is contained in:
committed by
Thomas Darimont
parent
4b2ccbecb9
commit
d116d3825a
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.connection;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractConnectionUnitTestBase<T> {
|
||||
|
||||
private T nativeRedisConnectionMock;
|
||||
|
||||
protected T getNativeRedisConnectionMock() {
|
||||
|
||||
if (this.nativeRedisConnectionMock == null) {
|
||||
Class<T> type = resolveReturnedClassFromGernericType();
|
||||
this.nativeRedisConnectionMock = Mockito.mock(type);
|
||||
}
|
||||
|
||||
return this.nativeRedisConnectionMock;
|
||||
}
|
||||
|
||||
protected T verifyNativeConnectionInvocation() {
|
||||
return Mockito.verify(getNativeRedisConnectionMock(), Mockito.times(1));
|
||||
}
|
||||
|
||||
protected void setNativeRedisConnectionMock(T nativeRedisConnectionMock) {
|
||||
this.nativeRedisConnectionMock = nativeRedisConnectionMock;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<T> resolveReturnedClassFromGernericType() {
|
||||
|
||||
ParameterizedType parameterizedType = resolveReturnedClassFromGernericType(getClass());
|
||||
return (Class<T>) parameterizedType.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private ParameterizedType resolveReturnedClassFromGernericType(Class<?> clazz) {
|
||||
|
||||
Object genericSuperclass = clazz.getGenericSuperclass();
|
||||
if (genericSuperclass instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
|
||||
Type rawtype = parameterizedType.getRawType();
|
||||
if (AbstractConnectionUnitTestBase.class.equals(rawtype)) {
|
||||
return parameterizedType;
|
||||
}
|
||||
}
|
||||
|
||||
return resolveReturnedClassFromGernericType(clazz.getSuperclass());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption;
|
||||
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
@@ -1699,6 +1700,16 @@ public class DefaultStringRedisConnectionTests {
|
||||
verifyResults(Arrays.asList(1L));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void testShutdownInDelegatedCorrectlyToNativeConnection() {
|
||||
|
||||
connection.shutdown(ShutdownOption.NOSAVE);
|
||||
verify(nativeConnection, times(1)).shutdown(eq(ShutdownOption.NOSAVE));
|
||||
}
|
||||
|
||||
protected List<Object> getResults() {
|
||||
return actual;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.connection.jedis;
|
||||
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Matchers;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionUnitTestBase;
|
||||
import org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionUnitTestSuite.JedisConnectionPipelineUnitTests;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionUnitTestSuite.JedisConnectionUnitTests;
|
||||
|
||||
import redis.clients.jedis.Client;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ JedisConnectionUnitTests.class, JedisConnectionPipelineUnitTests.class })
|
||||
public class JedisConnectionUnitTestSuite {
|
||||
|
||||
public static class JedisConnectionUnitTests extends AbstractConnectionUnitTestBase<Client> {
|
||||
|
||||
protected JedisConnection connection;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
connection = new JedisConnection(new MockedClientJedis("http://localhost:1234", getNativeRedisConnectionMock()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNullShouldDelegateCommandCorrectly() {
|
||||
|
||||
connection.shutdown(null);
|
||||
|
||||
verifyNativeConnectionInvocation().shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownNosaveShouldBeSentCorrectlyUsingLuaScript() {
|
||||
|
||||
connection.shutdown(ShutdownOption.NOSAVE);
|
||||
|
||||
ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
|
||||
verifyNativeConnectionInvocation().eval(captor.capture(), Matchers.any(byte[].class),
|
||||
Matchers.any(byte[][].class));
|
||||
|
||||
assertThat(captor.getValue(), equalTo("return redis.call('SHUTDOWN','NOSAVE')".getBytes()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownSaveShouldBeSentCorrectlyUsingLuaScript() {
|
||||
|
||||
connection.shutdown(ShutdownOption.SAVE);
|
||||
|
||||
ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
|
||||
verifyNativeConnectionInvocation().eval(captor.capture(), Matchers.any(byte[].class),
|
||||
Matchers.any(byte[][].class));
|
||||
|
||||
assertThat(captor.getValue(), equalTo("return redis.call('SHUTDOWN','SAVE')".getBytes()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class JedisConnectionPipelineUnitTests extends JedisConnectionUnitTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
connection.openPipeline();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Override
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void shutdownNosaveShouldBeSentCorrectlyUsingLuaScript() {
|
||||
super.shutdownNosaveShouldBeSentCorrectlyUsingLuaScript();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Override
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void shutdownSaveShouldBeSentCorrectlyUsingLuaScript() {
|
||||
super.shutdownSaveShouldBeSentCorrectlyUsingLuaScript();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Jedis} extension allowing to use mocked object as {@link Client}.
|
||||
*/
|
||||
private static class MockedClientJedis extends Jedis {
|
||||
|
||||
public MockedClientJedis(String host, Client client) {
|
||||
super(host);
|
||||
this.client = client;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.connection.jredis;
|
||||
|
||||
import org.jredis.JRedis;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionUnitTestBase;
|
||||
import org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class JRedisConnectionUnitTests extends AbstractConnectionUnitTestBase<JRedis> {
|
||||
|
||||
private JredisConnection connection;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
connection = new JredisConnection(getNativeRedisConnectionMock());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void shutdownSaveShouldThrowUnsupportedOperationException() {
|
||||
connection.shutdown(ShutdownOption.SAVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void shutdownNosaveShouldThrowUnsupportedOperationException() {
|
||||
connection.shutdown(ShutdownOption.NOSAVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void shutdownWithNullShouldThrowUnsupportedOperationException() {
|
||||
connection.shutdown(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionUnitTestBase;
|
||||
import org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionUnitTestSuite.LettuceConnectionUnitTests;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionUnitTestSuite.LettucePipelineConnectionUnitTests;
|
||||
|
||||
import com.lambdaworks.redis.RedisAsyncConnection;
|
||||
import com.lambdaworks.redis.RedisClient;
|
||||
import com.lambdaworks.redis.codec.RedisCodec;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({ LettuceConnectionUnitTests.class, LettucePipelineConnectionUnitTests.class })
|
||||
public class LettuceConnectionUnitTestSuite {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static class LettuceConnectionUnitTests extends AbstractConnectionUnitTestBase<RedisAsyncConnection> {
|
||||
|
||||
protected LettuceConnection connection;
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
RedisClient clientMock = mock(RedisClient.class);
|
||||
when(clientMock.connectAsync((RedisCodec) any())).thenReturn(getNativeRedisConnectionMock());
|
||||
connection = new LettuceConnection(0, clientMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNullOpionsIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(null);
|
||||
verifyNativeConnectionInvocation().shutdown(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNosaveOptionIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(ShutdownOption.NOSAVE);
|
||||
verifyNativeConnectionInvocation().shutdown(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithSaveOptionIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(ShutdownOption.SAVE);
|
||||
verifyNativeConnectionInvocation().shutdown(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LettucePipelineConnectionUnitTests extends LettuceConnectionUnitTests {
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
this.connection.openPipeline();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.connection.srp;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionUnitTestBase;
|
||||
import org.springframework.data.redis.connection.RedisServerCommands.ShutdownOption;
|
||||
import org.springframework.data.redis.connection.srp.SrpConnectionUnitTestSuite.SrpConnectionPiplineUnitTests;
|
||||
import org.springframework.data.redis.connection.srp.SrpConnectionUnitTestSuite.SrpConnectionUnitTests;
|
||||
|
||||
import redis.client.RedisClient;
|
||||
import redis.client.RedisClient.Pipeline;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({ SrpConnectionUnitTests.class, SrpConnectionPiplineUnitTests.class })
|
||||
public class SrpConnectionUnitTestSuite {
|
||||
|
||||
public static class SrpConnectionUnitTests extends AbstractConnectionUnitTestBase<RedisClient> {
|
||||
|
||||
protected SrpConnection connection;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
connection = new SrpConnection(getNativeRedisConnectionMock());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNullOpionsIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(null);
|
||||
verifyNativeConnectionInvocation().shutdown("SAVE".getBytes(Charsets.UTF_8), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithSaveIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(ShutdownOption.SAVE);
|
||||
verifyNativeConnectionInvocation().shutdown("SAVE".getBytes(Charsets.UTF_8), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNosaveIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(ShutdownOption.NOSAVE);
|
||||
verifyNativeConnectionInvocation().shutdown("NOSAVE".getBytes(Charsets.UTF_8), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SrpConnectionPiplineUnitTests extends AbstractConnectionUnitTestBase<Pipeline> {
|
||||
|
||||
protected SrpConnection connection;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
RedisClient clientMock = mock(RedisClient.class);
|
||||
connection = new SrpConnection(clientMock);
|
||||
when(clientMock.pipeline()).thenReturn(getNativeRedisConnectionMock());
|
||||
|
||||
connection.openPipeline();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNullOpionsIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(null);
|
||||
verifyNativeConnectionInvocation().shutdown("SAVE".getBytes(Charsets.UTF_8), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithSaveIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(ShutdownOption.SAVE);
|
||||
verifyNativeConnectionInvocation().shutdown("SAVE".getBytes(Charsets.UTF_8), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-184
|
||||
*/
|
||||
@Test
|
||||
public void shutdownWithNosaveIsCalledCorrectly() {
|
||||
|
||||
connection.shutdown(ShutdownOption.NOSAVE);
|
||||
verifyNativeConnectionInvocation().shutdown("NOSAVE".getBytes(Charsets.UTF_8), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user