From 9e1b60f86fa72f44a49da2739813bfd2d584d314 Mon Sep 17 00:00:00 2001 From: seakider Date: Wed, 12 Feb 2025 00:08:12 +0800 Subject: [PATCH 1/4] Feature - Support for OBJECT command Signed-off-by: seakider --- .../java/org/redisson/RedissonObject.java | 31 +++++ .../main/java/org/redisson/api/RObject.java | 20 +++ .../java/org/redisson/api/RObjectAsync.java | 21 ++++ .../org/redisson/api/RObjectReactive.java | 21 ++++ .../main/java/org/redisson/api/RObjectRx.java | 21 ++++ .../org/redisson/api/RedisObjectEncoding.java | 119 ++++++++++++++++++ .../client/protocol/RedisCommands.java | 10 ++ .../java/org/redisson/RedisDockerTest.java | 2 + .../java/org/redisson/RedissonBucketTest.java | 59 ++++++++- 9 files changed, 300 insertions(+), 4 deletions(-) create mode 100644 redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java diff --git a/redisson/src/main/java/org/redisson/RedissonObject.java b/redisson/src/main/java/org/redisson/RedissonObject.java index dc2fe2433..7415b8434 100644 --- a/redisson/src/main/java/org/redisson/RedissonObject.java +++ b/redisson/src/main/java/org/redisson/RedissonObject.java @@ -27,6 +27,7 @@ import org.redisson.client.protocol.RedisCommands; import org.redisson.client.protocol.pubsub.PubSubType; import org.redisson.command.BatchService; import org.redisson.command.CommandAsyncExecutor; +import org.redisson.api.RedisObjectEncoding; import org.redisson.connection.ServiceManager; import org.redisson.misc.CompletableFutureWrapper; import org.redisson.misc.Hash; @@ -606,11 +607,41 @@ public abstract class RedissonObject implements RObject { return get(getIdleTimeAsync()); } + @Override + public int getReferenceCount() { + return get(getReferenceCountAsync()); + } + + @Override + public int getAccessFrequency() { + return get(getAccessFrequencyAsync()); + } + + @Override + public RedisObjectEncoding getInternalEncoding() { + return get(getInternalEncodingAsync()); + } + @Override public RFuture getIdleTimeAsync() { return commandExecutor.writeAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.OBJECT_IDLETIME, getRawName()); } + @Override + public RFuture getReferenceCountAsync() { + return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.OBJECT_REFCOUNT, getRawName()); + } + + @Override + public RFuture getAccessFrequencyAsync() { + return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.OBJECT_FREQ, getRawName()); + } + + @Override + public RFuture getInternalEncodingAsync() { + return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.OBJECT_ENCODING, getRawName()); + } + protected final void removeListener(int listenerId, String... names) { for (String name : names) { RPatternTopic topic = new RedissonPatternTopic(StringCodec.INSTANCE, commandExecutor, name); diff --git a/redisson/src/main/java/org/redisson/api/RObject.java b/redisson/src/main/java/org/redisson/api/RObject.java index 6bab032fa..859324e8d 100644 --- a/redisson/src/main/java/org/redisson/api/RObject.java +++ b/redisson/src/main/java/org/redisson/api/RObject.java @@ -34,6 +34,26 @@ public interface RObject extends RObjectAsync { */ Long getIdleTime(); + /** + * Returns count of references over this object. + * + * @return count of reference + */ + int getReferenceCount(); + + /** + * Returns the logarithmic access frequency counter over this object. + * + * @return frequency counter + */ + int getAccessFrequency(); + + /** + * Returns the internal encoding for the Redis object + * + * @return internal encoding + */ + RedisObjectEncoding getInternalEncoding(); /** * Returns bytes amount used by object in Redis memory. * diff --git a/redisson/src/main/java/org/redisson/api/RObjectAsync.java b/redisson/src/main/java/org/redisson/api/RObjectAsync.java index 6903974d9..79ef75afa 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectAsync.java +++ b/redisson/src/main/java/org/redisson/api/RObjectAsync.java @@ -32,6 +32,27 @@ public interface RObjectAsync { */ RFuture getIdleTimeAsync(); + /** + * Returns count of references over this object. + * + * @return count of reference + */ + RFuture getReferenceCountAsync(); + + /** + * Returns the logarithmic access frequency counter over this object. + * + * @return frequency counter + */ + RFuture getAccessFrequencyAsync(); + + /** + * Returns the internal encoding for the Redis object + * + * @return internal encoding + */ + RFuture getInternalEncodingAsync(); + /** * Returns bytes amount used by object in Redis memory. * diff --git a/redisson/src/main/java/org/redisson/api/RObjectReactive.java b/redisson/src/main/java/org/redisson/api/RObjectReactive.java index c4f682ea5..978d6d74f 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectReactive.java +++ b/redisson/src/main/java/org/redisson/api/RObjectReactive.java @@ -36,6 +36,27 @@ public interface RObjectReactive { */ Mono getIdleTime(); + /** + * Returns count of references over this object. + * + * @return count of reference + */ + Mono getReferenceCount(); + + /** + * Returns the logarithmic access frequency counter over this object. + * + * @return frequency counter + */ + Mono getAccessFrequency(); + + /** + * Returns the internal encoding for the Redis object + * + * @return internal encoding + */ + Mono getInternalEncoding(); + String getName(); Codec getCodec(); diff --git a/redisson/src/main/java/org/redisson/api/RObjectRx.java b/redisson/src/main/java/org/redisson/api/RObjectRx.java index 6a3e0a58e..7c8f102aa 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectRx.java +++ b/redisson/src/main/java/org/redisson/api/RObjectRx.java @@ -37,6 +37,27 @@ public interface RObjectRx { */ Single getIdleTime(); + /** + * Returns count of references over this object. + * + * @return count of reference + */ + Single getReferenceCount(); + + /** + * Returns the logarithmic access frequency counter over this object. + * + * @return frequency counter + */ + Single getAccessFrequency(); + + /** + * Returns the internal encoding for the Redis object + * + * @return internal encoding + */ + Single getInternalEncoding(); + String getName(); Codec getCodec(); diff --git a/redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java b/redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java new file mode 100644 index 000000000..51962756d --- /dev/null +++ b/redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2013-2024 Nikita Koksharov + * + * 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.redisson.api; + +/** + * enum type from https://redis.io/docs/latest/commands/object-encoding/ + * + * @author seakider + */ +public enum RedisObjectEncoding { + /** + * Normal string encoding. + */ + RAW("raw"), + + /** + * Strings representing integers in a 64-bit signed interval. + */ + INT("int"), + + /** + * Strings with lengths up to the hardcoded limit of OBJ_ENCODING_EMBSTR_SIZE_LIMIT or 44 bytes. + */ + EMBSTR("embstr"), + + /** + * An old list encoding. + * No longer used. + */ + LINKEDLIST("linkedlist"), + + /** + * A space-efficient encoding used for small lists. + * Redis <= 6.2 + */ + ZIPLIST("ziplist"), + + /** + * A space-efficient encoding used for small lists. + * Redis >= 7.0 + */ + LISTPACK("listpack"), + + /** + * Encoded as linkedlist of ziplists or listpacks. + */ + QUICKLIST("quicklist"), + + /** + * Normal set encoding. + */ + HASHTABLE("hashtable"), + + /** + * Small sets composed solely of integers encoding. + */ + INTSET("intset"), + + /** + * An old hash encoding. + * No longer used + */ + ZIPMAP("zipmap"), + + /** + * Normal sorted set encoding + */ + SKIPLIST("skiplist"), + + /** + * Encoded as a radix tree of listpacks + */ + STREAM("stream"), + + /** + * Key is not exist. + */ + NULL("nonexistence"), + + /** + * This means redis support new type and this Enum not defined. + */ + UNKNOWN("unknown"); + + private final String type; + + RedisObjectEncoding(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public static RedisObjectEncoding valueOfEncoding(Object object) { + if (object == null) { + return NULL; + } + String value = (String) object; + for (RedisObjectEncoding encoding : RedisObjectEncoding.values()) { + if (value.equals(encoding.getType())) + return encoding; + } + return UNKNOWN; + } +} diff --git a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java index 28716d4bc..e30e2e1c6 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -26,6 +26,7 @@ import org.redisson.client.protocol.decoder.*; import org.redisson.client.protocol.pubsub.PubSubStatusDecoder; import org.redisson.cluster.ClusterNodeInfo; import org.redisson.codec.CompositeCodec; +import org.redisson.api.RedisObjectEncoding; import java.time.Duration; import java.time.Instant; @@ -733,6 +734,15 @@ public interface RedisCommands { RedisStrictCommand NOT_EXISTS = new RedisStrictCommand("EXISTS", new BooleanNumberReplayConvertor(1L)); RedisStrictCommand OBJECT_IDLETIME = new RedisStrictCommand("OBJECT", "IDLETIME", new LongReplayConvertor()); + RedisStrictCommand OBJECT_REFCOUNT = new RedisStrictCommand("OBJECT", "REFCOUNT", new IntegerReplayConvertor(0)); + RedisStrictCommand OBJECT_FREQ = new RedisStrictCommand("OBJECT", "FREQ", new IntegerReplayConvertor(0)); + RedisStrictCommand OBJECT_ENCODING = new RedisStrictCommand<>("OBJECT", "ENCODING", new Convertor() { + @Override + public RedisObjectEncoding convert(Object obj) { + return RedisObjectEncoding.valueOfEncoding(obj); + } + }); + RedisStrictCommand MEMORY_USAGE = new RedisStrictCommand("MEMORY", "USAGE", new LongReplayConvertor()); RedisStrictCommand> MEMORY_STATS = new RedisStrictCommand<>("MEMORY", "STATS", new StringMapReplayDecoder()); RedisStrictCommand RENAMENX = new RedisStrictCommand("RENAMENX", new BooleanReplayConvertor()); diff --git a/redisson/src/test/java/org/redisson/RedisDockerTest.java b/redisson/src/test/java/org/redisson/RedisDockerTest.java index 525db392e..7ddac2bd3 100644 --- a/redisson/src/test/java/org/redisson/RedisDockerTest.java +++ b/redisson/src/test/java/org/redisson/RedisDockerTest.java @@ -34,6 +34,8 @@ public class RedisDockerTest { protected static final String NOTIFY_KEYSPACE_EVENTS = "--notify-keyspace-events"; + protected static final String MAXMEMORY_POLICY = "--maxmemory-policy"; + protected static final GenericContainer REDIS = createRedis(); protected static final Protocol protocol = Protocol.RESP2; diff --git a/redisson/src/test/java/org/redisson/RedissonBucketTest.java b/redisson/src/test/java/org/redisson/RedissonBucketTest.java index f23503947..97c368155 100755 --- a/redisson/src/test/java/org/redisson/RedissonBucketTest.java +++ b/redisson/src/test/java/org/redisson/RedissonBucketTest.java @@ -6,14 +6,13 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import org.redisson.api.DeletedObjectListener; -import org.redisson.api.ExpiredObjectListener; -import org.redisson.api.RBucket; -import org.redisson.api.RedissonClient; +import org.redisson.api.*; import org.redisson.api.listener.SetObjectListener; import org.redisson.api.listener.TrackingListener; import org.redisson.api.options.PlainOptions; import org.redisson.client.RedisResponseTimeoutException; +import org.redisson.client.codec.IntegerCodec; +import org.redisson.client.codec.LongCodec; import org.redisson.client.codec.StringCodec; import org.redisson.config.Config; import org.redisson.config.Protocol; @@ -298,6 +297,58 @@ public class RedissonBucketTest extends RedisDockerTest { assertThat(al.getIdleTime()).isBetween(4L, 6L); } + @Test + public void testReferenceCount() { + RBucket al = redisson.getBucket("test"); + assertThat(al.getReferenceCount()).isEqualTo(0); + + al.set(10000); + assertThat(al.getReferenceCount()).isEqualTo(1); + } + + @Test + public void testAccessFrequency() { + testWithParams(redisson -> { + RBucket al = redisson.getBucket("test"); + assertThat(al.getAccessFrequency()).isEqualTo(0); + al.set(10000); + al.get(); + assertThat(al.getAccessFrequency()).isGreaterThan(1); + }, MAXMEMORY_POLICY, "allkeys-lfu"); + } + + @Test + public void testInternalEncoding() { + RBucket al = redisson.getBucket("test"); + assertThat(al.getInternalEncoding()).isEqualTo(RedisObjectEncoding.NULL); + al.set(123); + assertThat(al.getInternalEncoding()).isEqualTo(RedisObjectEncoding.EMBSTR); + + RList list=redisson.getList("list"); + list.addAll(Arrays.asList("a","b","c")); + assertThat(list.getInternalEncoding()).isEqualTo(RedisObjectEncoding.LISTPACK); + + RMap map = redisson.getMap("map"); + map.put(1, "12"); + map.put(2, "33"); + map.put(3, "43"); + assertThat(map.getInternalEncoding()).isEqualTo(RedisObjectEncoding.LISTPACK); + + RSet set = redisson.getSet("set", IntegerCodec.INSTANCE); + set.add(1); + set.add(2); + set.add(3); + assertThat(set.getInternalEncoding()).isEqualTo(RedisObjectEncoding.INTSET); + + RSortedSet sortedSet = redisson.getSortedSet("sortedSet", LongCodec.INSTANCE); + sortedSet.add(2L); + sortedSet.add(0L); + sortedSet.add(1L); + sortedSet.add(5L); + assertThat(sortedSet.getInternalEncoding()).isEqualTo(RedisObjectEncoding.LISTPACK); + + } + @Test public void testDeletedListener() { testWithParams(redisson -> { From 8f7292fb3547f99c8bf84b17bf2cb576ddc19e5b Mon Sep 17 00:00:00 2001 From: seakider Date: Wed, 12 Feb 2025 19:20:17 +0800 Subject: [PATCH 2/4] Feature - Support for OBJECT command Signed-off-by: seakider --- .../src/main/java/org/redisson/RedissonObject.java | 6 +++--- ...{RedisObjectEncoding.java => ObjectEncoding.java} | 8 ++++---- redisson/src/main/java/org/redisson/api/RObject.java | 2 +- .../src/main/java/org/redisson/api/RObjectAsync.java | 2 +- .../main/java/org/redisson/api/RObjectReactive.java | 2 +- .../src/main/java/org/redisson/api/RObjectRx.java | 2 +- .../org/redisson/client/protocol/RedisCommands.java | 8 ++++---- .../test/java/org/redisson/RedissonBucketTest.java | 12 ++++++------ 8 files changed, 21 insertions(+), 21 deletions(-) rename redisson/src/main/java/org/redisson/api/{RedisObjectEncoding.java => ObjectEncoding.java} (91%) diff --git a/redisson/src/main/java/org/redisson/RedissonObject.java b/redisson/src/main/java/org/redisson/RedissonObject.java index 7415b8434..1cbfcb606 100644 --- a/redisson/src/main/java/org/redisson/RedissonObject.java +++ b/redisson/src/main/java/org/redisson/RedissonObject.java @@ -27,7 +27,7 @@ import org.redisson.client.protocol.RedisCommands; import org.redisson.client.protocol.pubsub.PubSubType; import org.redisson.command.BatchService; import org.redisson.command.CommandAsyncExecutor; -import org.redisson.api.RedisObjectEncoding; +import org.redisson.api.ObjectEncoding; import org.redisson.connection.ServiceManager; import org.redisson.misc.CompletableFutureWrapper; import org.redisson.misc.Hash; @@ -618,7 +618,7 @@ public abstract class RedissonObject implements RObject { } @Override - public RedisObjectEncoding getInternalEncoding() { + public ObjectEncoding getInternalEncoding() { return get(getInternalEncodingAsync()); } @@ -638,7 +638,7 @@ public abstract class RedissonObject implements RObject { } @Override - public RFuture getInternalEncodingAsync() { + public RFuture getInternalEncodingAsync() { return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.OBJECT_ENCODING, getRawName()); } diff --git a/redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java b/redisson/src/main/java/org/redisson/api/ObjectEncoding.java similarity index 91% rename from redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java rename to redisson/src/main/java/org/redisson/api/ObjectEncoding.java index 51962756d..248907333 100644 --- a/redisson/src/main/java/org/redisson/api/RedisObjectEncoding.java +++ b/redisson/src/main/java/org/redisson/api/ObjectEncoding.java @@ -20,7 +20,7 @@ package org.redisson.api; * * @author seakider */ -public enum RedisObjectEncoding { +public enum ObjectEncoding { /** * Normal string encoding. */ @@ -97,7 +97,7 @@ public enum RedisObjectEncoding { private final String type; - RedisObjectEncoding(String type) { + ObjectEncoding(String type) { this.type = type; } @@ -105,12 +105,12 @@ public enum RedisObjectEncoding { return type; } - public static RedisObjectEncoding valueOfEncoding(Object object) { + public static ObjectEncoding valueOfEncoding(Object object) { if (object == null) { return NULL; } String value = (String) object; - for (RedisObjectEncoding encoding : RedisObjectEncoding.values()) { + for (ObjectEncoding encoding : ObjectEncoding.values()) { if (value.equals(encoding.getType())) return encoding; } diff --git a/redisson/src/main/java/org/redisson/api/RObject.java b/redisson/src/main/java/org/redisson/api/RObject.java index 859324e8d..567d7953d 100644 --- a/redisson/src/main/java/org/redisson/api/RObject.java +++ b/redisson/src/main/java/org/redisson/api/RObject.java @@ -53,7 +53,7 @@ public interface RObject extends RObjectAsync { * * @return internal encoding */ - RedisObjectEncoding getInternalEncoding(); + ObjectEncoding getInternalEncoding(); /** * Returns bytes amount used by object in Redis memory. * diff --git a/redisson/src/main/java/org/redisson/api/RObjectAsync.java b/redisson/src/main/java/org/redisson/api/RObjectAsync.java index 79ef75afa..05d9ea460 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectAsync.java +++ b/redisson/src/main/java/org/redisson/api/RObjectAsync.java @@ -51,7 +51,7 @@ public interface RObjectAsync { * * @return internal encoding */ - RFuture getInternalEncodingAsync(); + RFuture getInternalEncodingAsync(); /** * Returns bytes amount used by object in Redis memory. diff --git a/redisson/src/main/java/org/redisson/api/RObjectReactive.java b/redisson/src/main/java/org/redisson/api/RObjectReactive.java index 978d6d74f..644a7ef44 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectReactive.java +++ b/redisson/src/main/java/org/redisson/api/RObjectReactive.java @@ -55,7 +55,7 @@ public interface RObjectReactive { * * @return internal encoding */ - Mono getInternalEncoding(); + Mono getInternalEncoding(); String getName(); diff --git a/redisson/src/main/java/org/redisson/api/RObjectRx.java b/redisson/src/main/java/org/redisson/api/RObjectRx.java index 7c8f102aa..c67309897 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectRx.java +++ b/redisson/src/main/java/org/redisson/api/RObjectRx.java @@ -56,7 +56,7 @@ public interface RObjectRx { * * @return internal encoding */ - Single getInternalEncoding(); + Single getInternalEncoding(); String getName(); diff --git a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java index e30e2e1c6..73e3666df 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -26,7 +26,7 @@ import org.redisson.client.protocol.decoder.*; import org.redisson.client.protocol.pubsub.PubSubStatusDecoder; import org.redisson.cluster.ClusterNodeInfo; import org.redisson.codec.CompositeCodec; -import org.redisson.api.RedisObjectEncoding; +import org.redisson.api.ObjectEncoding; import java.time.Duration; import java.time.Instant; @@ -736,10 +736,10 @@ public interface RedisCommands { RedisStrictCommand OBJECT_IDLETIME = new RedisStrictCommand("OBJECT", "IDLETIME", new LongReplayConvertor()); RedisStrictCommand OBJECT_REFCOUNT = new RedisStrictCommand("OBJECT", "REFCOUNT", new IntegerReplayConvertor(0)); RedisStrictCommand OBJECT_FREQ = new RedisStrictCommand("OBJECT", "FREQ", new IntegerReplayConvertor(0)); - RedisStrictCommand OBJECT_ENCODING = new RedisStrictCommand<>("OBJECT", "ENCODING", new Convertor() { + RedisStrictCommand OBJECT_ENCODING = new RedisStrictCommand<>("OBJECT", "ENCODING", new Convertor() { @Override - public RedisObjectEncoding convert(Object obj) { - return RedisObjectEncoding.valueOfEncoding(obj); + public ObjectEncoding convert(Object obj) { + return ObjectEncoding.valueOfEncoding(obj); } }); diff --git a/redisson/src/test/java/org/redisson/RedissonBucketTest.java b/redisson/src/test/java/org/redisson/RedissonBucketTest.java index 97c368155..34ca1d345 100755 --- a/redisson/src/test/java/org/redisson/RedissonBucketTest.java +++ b/redisson/src/test/java/org/redisson/RedissonBucketTest.java @@ -320,32 +320,32 @@ public class RedissonBucketTest extends RedisDockerTest { @Test public void testInternalEncoding() { RBucket al = redisson.getBucket("test"); - assertThat(al.getInternalEncoding()).isEqualTo(RedisObjectEncoding.NULL); + assertThat(al.getInternalEncoding()).isEqualTo(ObjectEncoding.NULL); al.set(123); - assertThat(al.getInternalEncoding()).isEqualTo(RedisObjectEncoding.EMBSTR); + assertThat(al.getInternalEncoding()).isEqualTo(ObjectEncoding.EMBSTR); RList list=redisson.getList("list"); list.addAll(Arrays.asList("a","b","c")); - assertThat(list.getInternalEncoding()).isEqualTo(RedisObjectEncoding.LISTPACK); + assertThat(list.getInternalEncoding()).isEqualTo(ObjectEncoding.LISTPACK); RMap map = redisson.getMap("map"); map.put(1, "12"); map.put(2, "33"); map.put(3, "43"); - assertThat(map.getInternalEncoding()).isEqualTo(RedisObjectEncoding.LISTPACK); + assertThat(map.getInternalEncoding()).isEqualTo(ObjectEncoding.LISTPACK); RSet set = redisson.getSet("set", IntegerCodec.INSTANCE); set.add(1); set.add(2); set.add(3); - assertThat(set.getInternalEncoding()).isEqualTo(RedisObjectEncoding.INTSET); + assertThat(set.getInternalEncoding()).isEqualTo(ObjectEncoding.INTSET); RSortedSet sortedSet = redisson.getSortedSet("sortedSet", LongCodec.INSTANCE); sortedSet.add(2L); sortedSet.add(0L); sortedSet.add(1L); sortedSet.add(5L); - assertThat(sortedSet.getInternalEncoding()).isEqualTo(RedisObjectEncoding.LISTPACK); + assertThat(sortedSet.getInternalEncoding()).isEqualTo(ObjectEncoding.LISTPACK); } From 2fe06b7a389a74e201afbb45177efd344f31a9b7 Mon Sep 17 00:00:00 2001 From: seakider Date: Fri, 14 Feb 2025 12:50:42 +0800 Subject: [PATCH 3/4] Fixed - Fair Lock attempt to compare nil with number Signed-off-by: seakider --- redisson/src/main/java/org/redisson/RedissonFairLock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redisson/src/main/java/org/redisson/RedissonFairLock.java b/redisson/src/main/java/org/redisson/RedissonFairLock.java index 9386e4f0a..158105546 100644 --- a/redisson/src/main/java/org/redisson/RedissonFairLock.java +++ b/redisson/src/main/java/org/redisson/RedissonFairLock.java @@ -218,7 +218,7 @@ public class RedissonFairLock extends RedissonLock implements RLock { // threadWaitTime "local lastThreadId = redis.call('lindex', KEYS[2], -1);" + "local ttl;" + - "if lastThreadId ~= false and lastThreadId ~= ARGV[2] then " + + "if lastThreadId ~= false and lastThreadId ~= ARGV[2] and redis.call('zscore', KEYS[3], lastThreadId) ~= false then " + "ttl = tonumber(redis.call('zscore', KEYS[3], lastThreadId)) - tonumber(ARGV[4]);" + "else " + "ttl = redis.call('pttl', KEYS[1]);" + From 815bafe59653af47edbb56e47f2b80721a3bb3f3 Mon Sep 17 00:00:00 2001 From: seakider Date: Sun, 16 Feb 2025 23:49:40 +0800 Subject: [PATCH 4/4] Improvement - validate PARAMS in search method Signed-off-by: seakider --- .../main/java/org/redisson/RedissonSearch.java | 3 +++ .../java/org/redisson/RedissonSearchTest.java | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/redisson/src/main/java/org/redisson/RedissonSearch.java b/redisson/src/main/java/org/redisson/RedissonSearch.java index 530c484ec..cf056f024 100644 --- a/redisson/src/main/java/org/redisson/RedissonSearch.java +++ b/redisson/src/main/java/org/redisson/RedissonSearch.java @@ -495,6 +495,9 @@ public class RedissonSearch implements RSearch { args.add(options.getCount()); } if (!options.getParams().isEmpty()) { + if (options.getDialect() == null || options.getDialect() < 2) { + throw new IllegalArgumentException("When use 'PARAMS', you should set DIALECT to 2 or greater than 2."); + } args.add("PARAMS"); args.add(options.getParams().size()*2); for (Map.Entry entry : options.getParams().entrySet()) { diff --git a/redisson/src/test/java/org/redisson/RedissonSearchTest.java b/redisson/src/test/java/org/redisson/RedissonSearchTest.java index cb70e5cac..0c8d16904 100644 --- a/redisson/src/test/java/org/redisson/RedissonSearchTest.java +++ b/redisson/src/test/java/org/redisson/RedissonSearchTest.java @@ -1,6 +1,7 @@ package org.redisson; import com.fasterxml.jackson.core.type.TypeReference; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.redisson.api.RJsonBucket; import org.redisson.api.RMap; @@ -48,7 +49,20 @@ public class RedissonSearchTest extends DockerRedisStackTest { return Objects.hash(name); } } - + + @Test + public void testSearchWithParam() { + RJsonBucket b = redisson.getJsonBucket("doc:1", StringCodec.INSTANCE); + b.set("[{\"arr\": [1, 2, 3]}, {\"val\": \"hello\"}, {\"val\": \"world\"}]"); + + RSearch s = redisson.getSearch(StringCodec.INSTANCE); + Assertions.assertThrows(IllegalArgumentException.class, () -> + s.search("idx", "*", QueryOptions.defaults() + .returnAttributes(new ReturnAttribute("arr"), + new ReturnAttribute("val")) + .params(Collections.singletonMap("12", "323")))); + } + @Test public void testSearchNoContent() { RMap m = redisson.getMap("doc:1", new CompositeCodec(StringCodec.INSTANCE, redisson.getConfig().getCodec()));