diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index 0b8e96ac1..91d812c4d 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -304,8 +304,8 @@ public class DefaultStringRedisConnection implements StringRedisConnection { delegate.mSet(tuple); } - public void mSetNX(Map tuple) { - delegate.mSetNX(tuple); + public Boolean mSetNX(Map tuple) { + return delegate.mSetNX(tuple); } public void multi() { @@ -919,8 +919,8 @@ public class DefaultStringRedisConnection implements StringRedisConnection { } - public void mSetNXString(Map tuple) { - delegate.mSetNX(serialize(tuple)); + public Boolean mSetNXString(Map tuple) { + return delegate.mSetNX(serialize(tuple)); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java index bf481da0c..a64297fdd 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisStringCommands.java @@ -44,7 +44,7 @@ public interface RedisStringCommands { void mSet(Map tuple); - void mSetNX(Map tuple); + Boolean mSetNX(Map tuple); Long incr(byte[] key); diff --git a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java index 274aef6d8..8de88419d 100644 --- a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java @@ -95,7 +95,7 @@ public interface StringRedisConnection extends RedisConnection { void mSetString(Map tuple); - void mSetNXString(Map tuple); + Boolean mSetNXString(Map tuple); Long incr(String key); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index f633119e4..a22f604ed 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -985,17 +985,17 @@ public class JedisConnection implements RedisConnection { } - public void mSetNX(Map tuples) { + public Boolean mSetNX(Map tuples) { try { if (isQueueing()) { transaction.msetnx(JedisUtils.convert(tuples)); - return; + return null; } if (isPipelined()) { pipeline.msetnx(JedisUtils.convert(tuples)); - return; + return null; } - jedis.msetnx(JedisUtils.convert(tuples)); + return JedisUtils.convertCodeReply(jedis.msetnx(JedisUtils.convert(tuples))); } catch (Exception ex) { throw convertJedisAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java index 9c3e1d0ab..ef76bacae 100644 --- a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java @@ -516,9 +516,9 @@ public class JredisConnection implements RedisConnection { } - public void mSetNX(Map tuple) { + public Boolean mSetNX(Map tuple) { try { - jredis.msetnx(tuple); + return jredis.msetnx(tuple); } catch (Exception ex) { throw convertJredisAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index 164717480..e5aab9e44 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -873,13 +873,13 @@ public class LettuceConnection implements RedisConnection { } - public void mSetNX(Map tuples) { + public Boolean mSetNX(Map tuples) { try { if (isPipelined()) { pipeline(getAsyncConnection().msetnx(tuples)); - return; + return null; } - getConnection().msetnx(tuples); + return getConnection().msetnx(tuples); } catch (Exception ex) { throw convertLettuceAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java index 5959aa1c9..0d0a19b43 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java @@ -802,13 +802,13 @@ public class SrpConnection implements RedisConnection { } - public void mSetNX(Map tuples) { + public Boolean mSetNX(Map tuples) { try { if (isPipelined()) { pipeline(pipeline.msetnx((Object[]) SrpUtils.convert(tuples))); - return; + return null; } - client.msetnx((Object[]) SrpUtils.convert(tuples)); + return SrpUtils.asBoolean(client.msetnx((Object[]) SrpUtils.convert(tuples))); } catch (Exception ex) { throw convertSrpAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java index 1ffe3eb20..99d239d49 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java @@ -149,9 +149,9 @@ class DefaultValueOperations extends AbstractOperations implements V } - public void multiSetIfAbsent(Map m) { + public Boolean multiSetIfAbsent(Map m) { if (m.isEmpty()) { - return; + return true; } final Map rawKeys = new LinkedHashMap(m.size()); @@ -160,11 +160,10 @@ class DefaultValueOperations extends AbstractOperations implements V rawKeys.put(rawKey(entry.getKey()), rawValue(entry.getValue())); } - execute(new RedisCallback() { + return execute(new RedisCallback() { - public Object doInRedis(RedisConnection connection) { - connection.mSetNX(rawKeys); - return null; + public Boolean doInRedis(RedisConnection connection) { + return connection.mSetNX(rawKeys); } }, true); } diff --git a/src/main/java/org/springframework/data/redis/core/ValueOperations.java b/src/main/java/org/springframework/data/redis/core/ValueOperations.java index b034f4d3b..2cbe1a5dc 100644 --- a/src/main/java/org/springframework/data/redis/core/ValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ValueOperations.java @@ -35,7 +35,7 @@ public interface ValueOperations { void multiSet(Map m); - void multiSetIfAbsent(Map m); + Boolean multiSetIfAbsent(Map m); V get(Object key); diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java index 8c26dda3b..70922eaef 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -865,9 +865,21 @@ public abstract class AbstractConnectionIntegrationTests { Map vals = new HashMap(); vals.put("height", "5"); vals.put("width", "1"); - connection.mSetNXString(vals); + actual.add(connection.mSetNXString(vals)); actual.add(connection.mGet("height", "width")); - verifyResults(Arrays.asList(new Object[] { Arrays.asList(new String[] { "5", "1" }) }), + verifyResults(Arrays.asList(new Object[] { true, Arrays.asList(new String[] { "5", "1" }) }), + actual); + } + + @Test + public void testMSetNxFailure() { + connection.set("height", "2"); + Map vals = new HashMap(); + vals.put("height", "5"); + vals.put("width", "1"); + actual.add(connection.mSetNXString(vals)); + actual.add(connection.mGet("height", "width")); + verifyResults(Arrays.asList(new Object[] { false, Arrays.asList(new String[] { "2", null }) }), actual); } diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java index aa6f98e74..e03f571fb 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java @@ -339,6 +339,18 @@ abstract public class AbstractConnectionPipelineIntegrationTests extends actual); } + @Test + public void testMSetNxFailure() { + connection.set("height", "2"); + Map vals = new HashMap(); + vals.put("height", "5"); + vals.put("width", "1"); + actual.add(connection.mSetNXString(vals)); + actual.add(connection.mGet("height", "width")); + verifyResults(Arrays.asList(new Object[] { 0l, Arrays.asList(new String[] { "2", null }) }), + actual); + } + @Test public void testSetNx() { actual.add(connection.setNX("notaround", "54")); diff --git a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java index de96cebb5..dcadd5a8e 100644 --- a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java @@ -80,6 +80,10 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat public void testMSetNx() { } + @Ignore("https://github.com/alphazero/jredis/issues/64 Protocol error: expected '$' got '*' on mset") + public void testMSetNxFailure() { + } + @Test public void testConnectionClosesWhenNotPooled() { connection.close(); diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java index ad9bc0cb5..48f039637 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java @@ -186,6 +186,18 @@ public class LettuceConnectionPipelineIntegrationTests extends actual); } + @Test + public void testMSetNxFailure() { + connection.set("height", "2"); + Map vals = new HashMap(); + vals.put("height", "5"); + vals.put("width", "1"); + actual.add(connection.mSetNXString(vals)); + actual.add(connection.mGet("height", "width")); + verifyResults(Arrays.asList(new Object[] { false, Arrays.asList(new String[] { "2", null }) }), + actual); + } + @Test public void testSetNx() { actual.add(connection.setNX("notaround", "54")); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java b/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java index de84403e0..f8c538c27 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java @@ -16,6 +16,11 @@ package org.springframework.data.redis.core; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import org.junit.After; import org.junit.Before; @@ -71,4 +76,23 @@ public class DefaultValueOperationsTests { valueOps.increment(key, -10d); assertEquals("1.9", valueOps.get(key)); } + + @Test + public void testMultiSetIfAbsent() { + Map keysAndValues = new HashMap(); + keysAndValues.put("foo", "bar"); + keysAndValues.put("baz", "test"); + assertTrue(valueOps.multiSetIfAbsent(keysAndValues)); + assertEquals(new HashSet(keysAndValues.values()), + new HashSet(valueOps.multiGet(keysAndValues.keySet()))); + } + + @Test + public void testMultiSetIfAbsentFailure() { + valueOps.set("foo", "alreadyset"); + Map keysAndValues = new HashMap(); + keysAndValues.put("foo", "bar"); + keysAndValues.put("baz", "test"); + assertFalse(valueOps.multiSetIfAbsent(keysAndValues)); + } }