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 78722fe4d..20f0b44b9 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 @@ class JedisClusterListCommands implements RedisListCommands { 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 fcf540e67..c4cf9928d 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.BinaryJedis; 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 @@ class JedisListCommands implements RedisListCommands { 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).get(Collections::singletonList); } /* 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 00980b8bd..88a5db381 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 @@ public abstract class AbstractConnectionIntegrationTests { 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 @@ public abstract class AbstractConnectionIntegrationTests { 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 @@ public abstract class AbstractConnectionIntegrationTests { 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 @@ public abstract class AbstractConnectionIntegrationTests { 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 @@ public abstract class AbstractConnectionIntegrationTests { 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 @@ public abstract class AbstractConnectionIntegrationTests { 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")); 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 6ffcd6b09..50f1b79be 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.Distanc 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 redis.clients.jedis.JedisPool; 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,64 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests { 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); + } }