diff --git a/pom.xml b/pom.xml index a5d3a47ec6..29392c4c73 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-redis - 2.5.0-SNAPSHOT + 2.5.0-GH-1957-SNAPSHOT Spring Data Redis diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java index 78722fe4de..20f0b44b9e 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterListCommands.java @@ -15,12 +15,13 @@ */ package org.springframework.data.redis.connection.jedis; +import redis.clients.jedis.params.LPosParams; + import java.util.Arrays; import java.util.Collections; import java.util.List; import org.springframework.dao.DataAccessException; -import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.RedisListCommands; import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback; @@ -68,7 +69,22 @@ public List lPos(byte[] key, byte[] element, @Nullable Integer rank, @Null Assert.notNull(key, "Key must not be null!"); Assert.notNull(element, "Element must not be null!"); - throw new InvalidDataAccessApiUsageException("LPOS is not supported by jedis."); + LPosParams params = new LPosParams(); + if (rank != null) { + params.rank(rank); + } + + try { + + if (count != null) { + return connection.getCluster().lpos(key, element, params, count); + } + + Long value = connection.getCluster().lpos(key, element, params); + return value != null ? Collections.singletonList(value) : Collections.emptyList(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } } /* diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisListCommands.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisListCommands.java index fcf540e67b..66b4d41197 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisListCommands.java @@ -19,12 +19,14 @@ import redis.clients.jedis.MultiKeyPipelineBase; import redis.clients.jedis.Protocol; +import java.util.Collections; import java.util.List; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.RedisListCommands; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import redis.clients.jedis.params.LPosParams; /** * @author Christoph Strobl @@ -61,7 +63,16 @@ public List lPos(byte[] key, byte[] element, @Nullable Integer rank, @Null Assert.notNull(key, "Key must not be null!"); Assert.notNull(element, "Element must not be null!"); - throw new InvalidDataAccessApiUsageException("LPOS is not supported by jedis."); + LPosParams params = new LPosParams(); + if(rank != null) { + params.rank(rank); + } + + if(count != null) { + return connection.invoke().just(BinaryJedis::lpos, MultiKeyPipelineBase::lpos, key, element, params, count); + } + + return connection.invoke().from(BinaryJedis::lpos, MultiKeyPipelineBase::lpos, key, element, params).getOrElse(Collections::singletonList, Collections::emptyList); } /* diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java index 8c3500772c..459f0f6252 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceListCommands.java @@ -71,7 +71,7 @@ public List lPos(byte[] key, byte[] element, @Nullable Integer rank, @Null return connection.invoke().just(RedisListAsyncCommands::lpos, key, element, count, args); } - return connection.invoke().from(RedisListAsyncCommands::lpos, key, element, args).get(Collections::singletonList); + return connection.invoke().from(RedisListAsyncCommands::lpos, key, element, args).getOrElse(Collections::singletonList, Collections::emptyList); } /* 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 dc4b1e0045..8e01f681b2 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -1404,9 +1404,8 @@ void testLPushMultiple() { verifyResults(Arrays.asList(2L, Arrays.asList("baz", "bar"))); } - @Test // DATAREDIS-1196 + @Test // DATAREDIS-1196, GH-1957 @EnabledOnCommand("LPOS") - @EnabledOnRedisDriver({ RedisDriver.LETTUCE }) void lPos() { actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); @@ -1415,9 +1414,8 @@ void lPos() { assertThat((List) getResults().get(1)).containsOnly(2L); } - @Test // DATAREDIS-1196 + @Test // DATAREDIS-1196, GH-1957 @EnabledOnCommand("LPOS") - @EnabledOnRedisDriver({ RedisDriver.LETTUCE }) void lPosRank() { actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); @@ -1426,9 +1424,8 @@ void lPosRank() { assertThat((List) getResults().get(1)).containsExactly(6L); } - @Test // DATAREDIS-1196 + @Test // DATAREDIS-1196, GH-1957 @EnabledOnCommand("LPOS") - @EnabledOnRedisDriver({ RedisDriver.LETTUCE }) void lPosNegativeRank() { actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); @@ -1437,9 +1434,8 @@ void lPosNegativeRank() { assertThat((List) getResults().get(1)).containsExactly(7L); } - @Test // DATAREDIS-1196 + @Test // DATAREDIS-1196, GH-1957 @EnabledOnCommand("LPOS") - @EnabledOnRedisDriver({ RedisDriver.LETTUCE }) void lPosCount() { actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); @@ -1448,9 +1444,8 @@ void lPosCount() { assertThat((List) getResults().get(1)).containsExactly(2L, 6L); } - @Test // DATAREDIS-1196 + @Test // DATAREDIS-1196, GH-1957 @EnabledOnCommand("LPOS") - @EnabledOnRedisDriver({ RedisDriver.LETTUCE }) void lPosRankCount() { actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); @@ -1459,9 +1454,8 @@ void lPosRankCount() { assertThat((List) getResults().get(1)).containsExactly(7L, 6L); } - @Test // DATAREDIS-1196 + @Test // DATAREDIS-1196, GH-1957 @EnabledOnCommand("LPOS") - @EnabledOnRedisDriver({ RedisDriver.LETTUCE }) void lPosCountZero() { actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); @@ -1470,6 +1464,16 @@ void lPosCountZero() { assertThat((List) getResults().get(1)).containsExactly(2L, 6L, 7L); } + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosNonExisting() { + + actual.add(connection.rPush("mylist", "a", "b", "c", "1", "2", "3", "c", "c")); + actual.add(connection.lPos("mylist", "x", null, null)); + + assertThat((List) getResults().get(1)).isEmpty(); + } + // Set operations @Test diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java index 6ffcd6b090..7029daaa19 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java @@ -25,6 +25,7 @@ import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*; import static org.springframework.data.redis.core.ScanOptions.*; +import org.springframework.data.redis.test.condition.EnabledOnCommand; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; @@ -32,6 +33,7 @@ import java.io.IOException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.*; import java.util.concurrent.TimeUnit; @@ -2472,4 +2474,74 @@ void evelShaShouldRunScript() { Long result = clusterConnection.scriptingCommands().evalSha(digest, ReturnType.VALUE, 1, keyAndArgs); assertThat(result).isEqualTo(1L); } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPos() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "c".getBytes(StandardCharsets.UTF_8), null, null); + + assertThat(result).containsOnly(2L); + } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosRank() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "c".getBytes(StandardCharsets.UTF_8), 2, null); + + assertThat(result).containsExactly(6L); + } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosNegativeRank() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "c".getBytes(StandardCharsets.UTF_8), -1, null); + + assertThat(result).containsExactly(7L); + } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosCount() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "c".getBytes(StandardCharsets.UTF_8), null, 2); + + assertThat(result).containsExactly(2L, 6L); + } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosRankCount() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "c".getBytes(StandardCharsets.UTF_8), -1, 2); + + assertThat(result).containsExactly(7L, 6L); + } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosCountZero() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "c".getBytes(StandardCharsets.UTF_8), null, 0); + + assertThat(result).containsExactly(2L, 6L, 7L); + } + + @Test // GH-1957 + @EnabledOnCommand("LPOS") + void lPosNonExisting() { + + nativeConnection.rpush(KEY_1, "a", "b", "c", "1", "2", "3", "c", "c"); + List result = clusterConnection.listCommands().lPos(KEY_1_BYTES, "x".getBytes(StandardCharsets.UTF_8), null, null); + + assertThat(result).isEmpty(); + } }