From 4a101df38f1ba7bf9883eccc056facc4cbacd898 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:30:54 +0600 Subject: [PATCH 1/8] Support Hash field expiration (Strings) --- Makefile | 2 +- .../redis/clients/jedis/CommandArguments.java | 42 +++- .../redis/clients/jedis/CommandObjects.java | 73 +++++- src/main/java/redis/clients/jedis/Jedis.java | 78 +++++++ .../redis/clients/jedis/PipeliningBase.java | 65 ++++++ .../java/redis/clients/jedis/Protocol.java | 1 + .../redis/clients/jedis/UnifiedJedis.java | 65 ++++++ .../clients/jedis/args/RawableFactory.java | 18 ++ .../clients/jedis/commands/HashCommands.java | 135 +++++++++++ .../jedis/commands/HashPipelineCommands.java | 27 +++ .../commands/jedis/HashesCommandsTest.java | 90 ++++++++ .../unified/HashesCommandsTestBase.java | 81 +++++++ .../pooled/PooledHashesCommandsTest.java | 1 + .../PipeliningBaseHashCommandsTest.java | 158 +++++++++++++ .../unified/UnifiedJedisHashCommandsTest.java | 210 ++++++++++++++++++ 15 files changed, 1035 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 1800f00d7e..fc6935486c 100644 --- a/Makefile +++ b/Makefile @@ -527,7 +527,7 @@ mvn-release: system-setup: sudo apt install -y gcc g++ - [ ! -e redis-git ] && git clone https://github.com/redis/redis.git --branch unstable --single-branch redis-git || true + [ ! -e redis-git ] && git clone https://github.com/redis/redis.git --branch hash-field-expiry-integ --single-branch redis-git || true $(MAKE) -C redis-git clean $(MAKE) -C redis-git diff --git a/src/main/java/redis/clients/jedis/CommandArguments.java b/src/main/java/redis/clients/jedis/CommandArguments.java index b9190245ce..c630ae76de 100644 --- a/src/main/java/redis/clients/jedis/CommandArguments.java +++ b/src/main/java/redis/clients/jedis/CommandArguments.java @@ -1,6 +1,7 @@ package redis.clients.jedis; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; @@ -29,6 +30,35 @@ public ProtocolCommand getCommand() { return (ProtocolCommand) args.get(0); } + public CommandArguments add(Rawable arg) { + args.add(arg); + return this; + } + + public CommandArguments add(byte[] arg) { + return add(RawableFactory.from(arg)); + } + + public CommandArguments add(boolean arg) { + return add(RawableFactory.from(arg)); + } + + public CommandArguments add(int arg) { + return add(RawableFactory.from(arg)); + } + + public CommandArguments add(long arg) { + return add(RawableFactory.from(arg)); + } + + public CommandArguments add(double arg) { + return add(RawableFactory.from(arg)); + } + + public CommandArguments add(String arg) { + return add(RawableFactory.from(arg)); + } + public CommandArguments add(Object arg) { if (arg == null) { throw new IllegalArgumentException("null is not a valid argument."); @@ -36,12 +66,14 @@ public CommandArguments add(Object arg) { args.add((Rawable) arg); } else if (arg instanceof byte[]) { args.add(RawableFactory.from((byte[]) arg)); + } else if (arg instanceof Boolean) { + args.add(RawableFactory.from((Boolean) arg)); } else if (arg instanceof Integer) { args.add(RawableFactory.from((Integer) arg)); + } else if (arg instanceof Long) { + args.add(RawableFactory.from((Long) arg)); } else if (arg instanceof Double) { args.add(RawableFactory.from((Double) arg)); - } else if (arg instanceof Boolean) { - args.add(RawableFactory.from((Boolean) arg ? 1 : 0)); } else if (arg instanceof float[]) { args.add(RawableFactory.from(RediSearchUtil.toByteArray((float[]) arg))); } else if (arg instanceof String) { @@ -87,14 +119,12 @@ public CommandArguments key(Object key) { } public final CommandArguments keys(Object... keys) { - for (Object key : keys) { - key(key); - } + Arrays.stream(keys).forEach(this::key); return this; } public final CommandArguments keys(Collection keys) { - keys.forEach(key -> key(key)); + keys.forEach(this::key); return this; } diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index 896ef38293..1e0ea2d0da 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -1140,10 +1140,6 @@ public final CommandObject> hscanNoValues(String key, String return new CommandObject<>(commandArguments(HSCAN).key(key).add(cursor).addParams(params).add(NOVALUES), BuilderFactory.SCAN_RESPONSE); } - public final CommandObject hstrlen(String key, String field) { - return new CommandObject<>(commandArguments(HSTRLEN).key(key).add(field), BuilderFactory.LONG); - } - public final CommandObject>> hscan(byte[] key, byte[] cursor, ScanParams params) { return new CommandObject<>(commandArguments(HSCAN).key(key).add(cursor).addParams(params), BuilderFactory.HSCAN_BINARY_RESPONSE); } @@ -1152,9 +1148,78 @@ public final CommandObject> hscanNoValues(byte[] key, byte[] return new CommandObject<>(commandArguments(HSCAN).key(key).add(cursor).addParams(params).add(NOVALUES), BuilderFactory.SCAN_BINARY_RESPONSE); } + public final CommandObject hstrlen(String key, String field) { + return new CommandObject<>(commandArguments(HSTRLEN).key(key).add(field), BuilderFactory.LONG); + } + public final CommandObject hstrlen(byte[] key, byte[] field) { return new CommandObject<>(commandArguments(HSTRLEN).key(key).add(field), BuilderFactory.LONG); } + + public final CommandObject> hexpire(String key, long seconds, String... fields) { + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpire(String key, long seconds, ExpiryOption condition, String... fields) { + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpire(String key, long milliseconds, String... fields) { + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields) { + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpireAt(String key, long unixTimeSeconds, String... fields) { + return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields) { + return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds).add(condition) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpireAt(String key, long unixTimeMillis, String... fields) { + return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields) { + return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis).add(condition) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpireTime(String key, String... fields) { + return new CommandObject<>(commandArguments(HEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpireTime(String key, String... fields) { + return new CommandObject<>(commandArguments(HPEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> httl(String key, String... fields) { + return new CommandObject<>(commandArguments(HTTL).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpttl(String key, String... fields) { + return new CommandObject<>(commandArguments(HPTTL).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpersist(String key, String... fields) { + return new CommandObject<>(commandArguments(HPERSIST).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } // Hash commands // Set commands diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 03a2bc1ed1..1a4b3010d5 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -9237,6 +9237,84 @@ public long hstrlen(final String key, final String field) { return connection.executeCommand(commandObjects.hstrlen(key, field)); } + @Override + public List hexpire(String key, long seconds, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpire(key, seconds, fields)); + } + + @Override + public List hexpire(String key, long seconds, ExpiryOption condition, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpire(key, seconds, condition, fields)); + } + + @Override + public List hpexpire(String key, long milliseconds, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpire(key, milliseconds, fields)); + } + + @Override + public List hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpire(key, milliseconds, condition, fields)); + } + + @Override + public List hexpireAt(String key, long unixTimeSeconds, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, fields)); + } + + @Override + public List hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, condition, fields)); + } + + @Override + public List hpexpireAt(String key, long unixTimeMillis, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, fields)); + } + + @Override + public List hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); + } + + @Override + public List hexpireTime(String key, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpireTime(key, fields)); + } + + @Override + public List hpexpireTime(String key, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpireTime(key, fields)); + } + + @Override + public List httl(String key, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.httl(key, fields)); + } + + @Override + public List hpttl(String key, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpttl(key, fields)); + } + + @Override + public List hpersist(String key, String... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpersist(key, fields)); + } + @Override public String memoryDoctor() { checkIsInMultiOrPipeline(); diff --git a/src/main/java/redis/clients/jedis/PipeliningBase.java b/src/main/java/redis/clients/jedis/PipeliningBase.java index 2dac5af712..8ce1375890 100644 --- a/src/main/java/redis/clients/jedis/PipeliningBase.java +++ b/src/main/java/redis/clients/jedis/PipeliningBase.java @@ -725,6 +725,71 @@ public Response hstrlen(String key, String field) { return appendCommand(commandObjects.hstrlen(key, field)); } + @Override + public Response> hexpire(String key, long seconds, String... fields) { + return appendCommand(commandObjects.hexpire(key, seconds, fields)); + } + + @Override + public Response> hexpire(String key, long seconds, ExpiryOption condition, String... fields) { + return appendCommand(commandObjects.hexpire(key, seconds, condition, fields)); + } + + @Override + public Response> hpexpire(String key, long milliseconds, String... fields) { + return appendCommand(commandObjects.hpexpire(key, milliseconds, fields)); + } + + @Override + public Response> hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields) { + return appendCommand(commandObjects.hpexpire(key, milliseconds, condition, fields)); + } + + @Override + public Response> hexpireAt(String key, long unixTimeSeconds, String... fields) { + return appendCommand(commandObjects.hexpireAt(key, unixTimeSeconds, fields)); + } + + @Override + public Response> hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields) { + return appendCommand(commandObjects.hexpireAt(key, unixTimeSeconds, condition, fields)); + } + + @Override + public Response> hpexpireAt(String key, long unixTimeMillis, String... fields) { + return appendCommand(commandObjects.hpexpireAt(key, unixTimeMillis, fields)); + } + + @Override + public Response> hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields) { + return appendCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); + } + + @Override + public Response> hexpireTime(String key, String... fields) { + return appendCommand(commandObjects.hexpireTime(key, fields)); + } + + @Override + public Response> hpexpireTime(String key, String... fields) { + return appendCommand(commandObjects.hpexpireTime(key, fields)); + } + + @Override + public Response> httl(String key, String... fields) { + return appendCommand(commandObjects.httl(key, fields)); + } + + @Override + public Response> hpttl(String key, String... fields) { + return appendCommand(commandObjects.hpttl(key, fields)); + } + + @Override + public Response> hpersist(String key, String... fields) { + return appendCommand(commandObjects.hpersist(key, fields)); + } + @Override public Response sadd(String key, String... members) { return appendCommand(commandObjects.sadd(key, members)); diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 531ee768c9..093a3463f7 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -254,6 +254,7 @@ public static enum Command implements ProtocolCommand { STRLEN, APPEND, SUBSTR, // <-- string SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, BITCOUNT, BITOP, BITFIELD, BITFIELD_RO, // <-- bit (string) HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, HSTRLEN, + HEXPIRE, HPEXPIRE, HEXPIREAT, HPEXPIREAT, HTTL, HPTTL, HEXPIRETIME, HPEXPIRETIME, HPERSIST, HRANDFIELD, HINCRBYFLOAT, // <-- hash RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, BLPOP, BRPOP, LINSERT, LPOS, RPOPLPUSH, BRPOPLPUSH, BLMOVE, LMOVE, LMPOP, BLMPOP, LPUSHX, RPUSHX, // <-- list diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 452798d303..27d1f81554 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -1600,6 +1600,71 @@ public ScanResult hscanNoValues(byte[] key, byte[] cursor, ScanParams pa public long hstrlen(byte[] key, byte[] field) { return executeCommand(commandObjects.hstrlen(key, field)); } + + @Override + public List hexpire(String key, long seconds, String... fields) { + return executeCommand(commandObjects.hexpire(key, seconds, fields)); + } + + @Override + public List hexpire(String key, long seconds, ExpiryOption condition, String... fields) { + return executeCommand(commandObjects.hexpire(key, seconds, condition, fields)); + } + + @Override + public List hpexpire(String key, long milliseconds, String... fields) { + return executeCommand(commandObjects.hpexpire(key, milliseconds, fields)); + } + + @Override + public List hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields) { + return executeCommand(commandObjects.hpexpire(key, milliseconds, condition, fields)); + } + + @Override + public List hexpireAt(String key, long unixTimeSeconds, String... fields) { + return executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, fields)); + } + + @Override + public List hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields) { + return executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, condition, fields)); + } + + @Override + public List hpexpireAt(String key, long unixTimeMillis, String... fields) { + return executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, fields)); + } + + @Override + public List hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields) { + return executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); + } + + @Override + public List hexpireTime(String key, String... fields) { + return executeCommand(commandObjects.hexpireTime(key, fields)); + } + + @Override + public List hpexpireTime(String key, String... fields) { + return executeCommand(commandObjects.hpexpireTime(key, fields)); + } + + @Override + public List httl(String key, String... fields) { + return executeCommand(commandObjects.httl(key, fields)); + } + + @Override + public List hpttl(String key, String... fields) { + return executeCommand(commandObjects.hpttl(key, fields)); + } + + @Override + public List hpersist(String key, String... fields) { + return executeCommand(commandObjects.hpersist(key, fields)); + } // Hash commands // Set commands diff --git a/src/main/java/redis/clients/jedis/args/RawableFactory.java b/src/main/java/redis/clients/jedis/args/RawableFactory.java index 8bce7f0e78..813ddd021b 100644 --- a/src/main/java/redis/clients/jedis/args/RawableFactory.java +++ b/src/main/java/redis/clients/jedis/args/RawableFactory.java @@ -10,6 +10,15 @@ */ public final class RawableFactory { + /** + * Get a {@link Rawable} from a {@code boolean}. + * @param b boolean value + * @return raw + */ + public static Rawable from(boolean b) { + return from(toByteArray(b)); + } + /** * Get a {@link Rawable} from an {@code int}. * @param i integer value @@ -19,6 +28,15 @@ public static Rawable from(int i) { return from(toByteArray(i)); } + /** + * Get a {@link Rawable} from a {@code long}. + * @param l long value + * @return raw + */ + public static Rawable from(long l) { + return from(toByteArray(l)); + } + /** * Get a {@link Rawable} from a {@code double}. * @param d numeric value diff --git a/src/main/java/redis/clients/jedis/commands/HashCommands.java b/src/main/java/redis/clients/jedis/commands/HashCommands.java index ef18e34aee..3be6ec1959 100644 --- a/src/main/java/redis/clients/jedis/commands/HashCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashCommands.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.Set; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -56,4 +57,138 @@ default ScanResult hscanNoValues(String key, String cursor) { ScanResult hscanNoValues(String key, String cursor, ScanParams params); long hstrlen(String key, String field); + + /** + * Set expiry for hash field using relative time to expire (seconds). + * + * @param key hash + * @param seconds time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpire(String key, long seconds, String... fields); + + /** + * Set expiry for hash field using relative time to expire (seconds). + * + * @param key hash + * @param seconds time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpire(String key, long seconds, ExpiryOption condition, String... fields); + + /** + * Set expiry for hash field using relative time to expire (milliseconds). + * + * @param key hash + * @param milliseconds time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpire(String key, long milliseconds, String... fields); + + /** + * Set expiry for hash field using relative time to expire (milliseconds). + * + * @param key hash + * @param milliseconds time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (seconds). + * + * @param key hash + * @param unixTimeSeconds time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpireAt(String key, long unixTimeSeconds, String... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (seconds). + * + * @param key hash + * @param unixTimeSeconds time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (milliseconds). + * + * @param key hash + * @param unixTimeMillis time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpireAt(String key, long unixTimeMillis, String... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (milliseconds). + * + * @param key hash + * @param unixTimeMillis time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields); + + /** + * Returns the expiration time of a hash field as a Unix timestamp, in seconds. + * + * @param key hash + * @param fields + * @return Expiration Unix timestamp in seconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hexpireTime(String key, String... fields); + + /** + * Returns the expiration time of a hash field as a Unix timestamp, in milliseconds. + * + * @param key hash + * @param fields + * @return Expiration Unix timestamp in milliseconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hpexpireTime(String key, String... fields); + + /** + * Returns the TTL in seconds of a hash field. + * + * @param key hash + * @param fields + * @return TTL in seconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List httl(String key, String... fields); + + /** + * Returns the TTL in milliseconds of a hash field. + * + * @param key hash + * @param fields + * @return TTL in milliseconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hpttl(String key, String... fields); + + /** + * Removes the expiration time for each specified field. + * + * @param key hash + * @param fields + * @return integer-reply: 1 if the expiration time was removed, + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hpersist(String key, String... fields); } diff --git a/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java index dabcac4e90..4de4839a9d 100644 --- a/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java @@ -5,6 +5,7 @@ import java.util.Set; import redis.clients.jedis.Response; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -57,4 +58,30 @@ default Response> hscanNoValues(String key, String cursor) { Response> hscanNoValues(String key, String cursor, ScanParams params); Response hstrlen(String key, String field); + + Response> hexpire(String key, long seconds, String... fields); + + Response> hexpire(String key, long seconds, ExpiryOption condition, String... fields); + + Response> hpexpire(String key, long milliseconds, String... fields); + + Response> hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields); + + Response> hexpireAt(String key, long unixTimeSeconds, String... fields); + + Response> hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields); + + Response> hpexpireAt(String key, long unixTimeMillis, String... fields); + + Response> hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields); + + Response> hexpireTime(String key, String... fields); + + Response> hpexpireTime(String key, String... fields); + + Response> httl(String key, String... fields); + + Response> hpttl(String key, String... fields); + + Response> hpersist(String key, String... fields); } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java index c07adc86b4..66f9061a2d 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java @@ -1,7 +1,13 @@ package redis.clients.jedis.commands.jedis; +import static java.util.Arrays.asList; + import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -29,6 +35,7 @@ import redis.clients.jedis.Pipeline; import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.Response; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.util.AssertUtil; @@ -49,6 +56,15 @@ public HashesCommandsTest(RedisProtocol protocol) { super(protocol); } + // TODO: remove + @org.junit.BeforeClass + public static void prepare() { + try (redis.clients.jedis.Jedis j = new redis.clients.jedis.Jedis(hnp)) { + j.auth("foobared"); + j.configSet("hash-max-listpack-entries", "0"); + } + } + @Test public void hset() { assertEquals(1, jedis.hset("foo", "bar", "car")); @@ -641,4 +657,78 @@ public void hrandfield() { assertEquals(5, bactual.size()); bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); } + + @Test + public void hexpireAndHttl() { + long seconds = 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(0L, 2L), jedis.hexpire("foo", -1, ExpiryOption.NX, "bar", "bared")); + + assertThat(jedis.httl("foo", "bar", "bare", "bared"), + contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hpexpireAndHpttl() { + long millis = 20_000; + + jedis.hset("foo", "bar", "car"); + assertEquals(asList(1L, -2L), jedis.hpexpire("foo", millis, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(2L, 0L), jedis.hpexpire("foo", -100, ExpiryOption.XX, "bar", "bared")); + + assertThat(jedis.hpttl("foo", "bar", "bare", "bared"), + contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hexpireAtAndExpireTime() { + long currSeconds = System.currentTimeMillis() / 1000; + long unixSeconds = currSeconds + 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpireAt("foo", unixSeconds, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(2L, 0L), jedis.hexpireAt("foo", currSeconds - 1, ExpiryOption.LT, "bar", "bared")); + + assertThat(jedis.hexpireTime("foo", "bar", "bare", "bared"), + contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + } + + @Test + public void hpexpireAtAndPexpireTime() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; + + jedis.hset("foo", "bar", "car"); + assertEquals(asList(1L, -2L), jedis.hpexpireAt("foo", unixMillis - 100, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(1L, 0L), jedis.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")); + + assertThat(jedis.hpexpireTime("foo", "bar", "bare", "bared"), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hpersist() { + long seconds = 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + + assertEquals(asList(1L, -1L, -2L), jedis.hpersist("foo", "bar", "bare", "bared")); + + assertThat(jedis.httl("foo", "bar", "bare", "bared"), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java index 401f29dbe3..1909423bab 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java @@ -1,7 +1,13 @@ package redis.clients.jedis.commands.unified; +import static java.util.Arrays.asList; + import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -25,6 +31,7 @@ import org.junit.Test; import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.util.AssertUtil; @@ -613,4 +620,78 @@ public void hrandfield() { assertEquals(5, bactual.size()); bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); } + + @Test + public void hexpireAndHttl() { + long seconds = 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(0L, 2L), jedis.hexpire("foo", -1, ExpiryOption.NX, "bar", "bared")); + + assertThat(jedis.httl("foo", "bar", "bare", "bared"), + contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hpexpireAndHpttl() { + long millis = 20_000; + + jedis.hset("foo", "bar", "car"); + assertEquals(asList(1L, -2L), jedis.hpexpire("foo", millis, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(2L, 0L), jedis.hpexpire("foo", -100, ExpiryOption.XX, "bar", "bared")); + + assertThat(jedis.hpttl("foo", "bar", "bare", "bared"), + contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hexpireAtAndExpireTime() { + long currSeconds = System.currentTimeMillis() / 1000; + long unixSeconds = currSeconds + 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpireAt("foo", unixSeconds, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(2L, 0L), jedis.hexpireAt("foo", currSeconds - 1, ExpiryOption.LT, "bar", "bared")); + + assertThat(jedis.hexpireTime("foo", "bar", "bare", "bared"), + contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + } + + @Test + public void hpexpireAtAndPexpireTime() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; + + jedis.hset("foo", "bar", "car"); + assertEquals(asList(1L, -2L), jedis.hpexpireAt("foo", unixMillis - 100, "bar", "bared")); + + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(1L, 0L), jedis.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")); + + assertThat(jedis.hpexpireTime("foo", "bar", "bare", "bared"), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hpersist() { + long seconds = 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + + assertEquals(asList(1L, -1L, -2L), jedis.hpersist("foo", "bar", "bare", "bared")); + + assertThat(jedis.httl("foo", "bar", "bare", "bared"), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java index bb5741d967..2be4582cd7 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java @@ -19,6 +19,7 @@ public PooledHashesCommandsTest(RedisProtocol protocol) { public void setUp() { jedis = PooledCommandsTestHelper.getPooled(protocol); PooledCommandsTestHelper.clearData(); + jedis.configSet("hash-max-listpack-entries", "0"); // TODO: remove } @After diff --git a/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java b/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java index b23cee6da2..fe656d95f9 100644 --- a/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java @@ -2,7 +2,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.in; import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.HashMap; @@ -12,6 +14,7 @@ import org.junit.Test; import redis.clients.jedis.Response; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -502,4 +505,159 @@ public void testHvalsBinary() { assertThat(response, is(predefinedResponse)); } + @Test + public void hexpire() { + String key = "hash"; + long seconds = 100; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hexpire(key, seconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpire(key, seconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireCondition() { + String key = "hash"; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hexpire(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpire(key, seconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpire() { + String key = "hash"; + long milliseconds = 10000; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpexpire(key, milliseconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpire(key, milliseconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireCondition() { + String key = "hash"; + long milliseconds = 10000; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpexpire(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpire(key, milliseconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireAt() { + String key = "hash"; + long seconds = 100; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hexpireAt(key, seconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpireAt(key, seconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireAtCondition() { + String key = "hash"; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hexpireAt(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpireAt(key, seconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireAt() { + String key = "hash"; + long milliseconds = 10000; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpexpireAt(key, milliseconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpireAt(key, milliseconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireAtCondition() { + String key = "hash"; + long milliseconds = 10000; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpexpireAt(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpireAt(key, milliseconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireTime() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hexpireTime(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpireTime(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireTime() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpexpireTime(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpireTime(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void httl() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.httl(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.httl(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpttl() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpttl(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpttl(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpersist() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + + when(commandObjects.hpersist(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpersist(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + } diff --git a/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java b/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java index c867e4d3e5..25e81a9b8e 100644 --- a/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java @@ -1,7 +1,9 @@ package redis.clients.jedis.mocked.unified; +import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -15,6 +17,7 @@ import java.util.Set; import org.junit.Test; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -764,4 +767,211 @@ public void testHvalsBinary() { verify(commandObjects).hvals(key); } + @Test + public void hexpire() { + String key = "hash"; + long seconds = 100; + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpire(key, seconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpire(key, seconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpire(key, seconds, fields); + } + + @Test + public void hexpireCondition() { + String key = "hash"; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpire(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpire(key, seconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpire(key, seconds, condition, fields); + } + + @Test + public void hpexpire() { + String key = "hash"; + long milliseconds = 10000; + String[] fields = { "one", "two", "three" }; + List expected = asList( 100L, 200L, 300L ); + + when(commandObjects.hpexpire(key, milliseconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpire(key, milliseconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpire(key, milliseconds, fields); + } + + @Test + public void hpexpireCondition() { + String key = "hash"; + long milliseconds = 10000; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + List expected = asList( 100L, 200L, 300L ); + + when(commandObjects.hpexpire(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpire(key, milliseconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpire(key, milliseconds, condition, fields); + } + + @Test + public void hexpireAt() { + String key = "hash"; + long seconds = 100; + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpireAt(key, seconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpireAt(key, seconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpireAt(key, seconds, fields); + } + + @Test + public void hexpireAtCondition() { + String key = "hash"; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpireAt(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpireAt(key, seconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpireAt(key, seconds, condition, fields); + } + + @Test + public void hpexpireAt() { + String key = "hash"; + long milliseconds = 10000; + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hpexpireAt(key, milliseconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpireAt(key, milliseconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpireAt(key, milliseconds, fields); + } + + @Test + public void hpexpireAtCondition() { + String key = "hash"; + long milliseconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hpexpireAt(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpireAt(key, milliseconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpireAt(key, milliseconds, condition, fields); + } + + @Test + public void hexpireTime() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + List expected = asList( 10L, 20L, 30L ); + + when(commandObjects.hexpireTime(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpireTime(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpireTime(key, fields); + } + + @Test + public void hpexpireTime() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + List expected = asList( 1000L, 2000L, 3000L ); + + when(commandObjects.hpexpireTime(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpireTime(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpireTime(key, fields); + } + + @Test + public void httl() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + List expected = asList( 10L, 20L, 30L ); + + when(commandObjects.httl(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.httl(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).httl(key, fields); + } + + @Test + public void hpttl() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + List expected = asList( 1000L, 2000L, 3000L ); + + when(commandObjects.hpttl(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpttl(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpttl(key, fields); + } + + @Test + public void hpersist() { + String key = "hash"; + String[] fields = { "one", "two", "three" }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hpersist(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpersist(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpersist(key, fields); + } + } From 06ac1ca1d42e8ac11080c3e593e778d20ffc4c44 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 2 May 2024 00:29:53 +0600 Subject: [PATCH 2/8] Support Hash field expiration (byte[]s) --- .../redis/clients/jedis/CommandObjects.java | 65 ++++++ src/main/java/redis/clients/jedis/Jedis.java | 78 +++++++ .../redis/clients/jedis/PipeliningBase.java | 65 ++++++ .../redis/clients/jedis/UnifiedJedis.java | 65 ++++++ .../jedis/commands/HashBinaryCommands.java | 134 +++++++++++ .../commands/HashPipelineBinaryCommands.java | 26 +++ .../commands/jedis/HashesCommandsTest.java | 74 ++++++ .../unified/HashesCommandsTestBase.java | 74 ++++++ .../cluster/ClusterHashesCommandsTest.java | 29 +++ .../PipeliningBaseHashCommandsTest.java | 161 +++++++++++++ .../unified/UnifiedJedisHashCommandsTest.java | 213 ++++++++++++++++++ 11 files changed, 984 insertions(+) create mode 100644 src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index 1e0ea2d0da..ab048d50b4 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -1196,6 +1196,46 @@ public final CommandObject> hpexpireAt(String key, long unixTimeMilli .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } + public final CommandObject> hexpire(byte[] key, long seconds, byte[]... fields) { + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields) { + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpire(byte[] key, long milliseconds, byte[]... fields) { + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields) { + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition).add(fields.length) + .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields) { + return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields) { + return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds).add(condition) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields) { + return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields) { + return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis).add(condition) + .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + } + public final CommandObject> hexpireTime(String key, String... fields) { return new CommandObject<>(commandArguments(HEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); @@ -1216,10 +1256,35 @@ public final CommandObject> hpttl(String key, String... fields) { BuilderFactory.LONG_LIST); } + public final CommandObject> hexpireTime(byte[] key, byte[]... fields) { + return new CommandObject<>(commandArguments(HEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpexpireTime(byte[] key, byte[]... fields) { + return new CommandObject<>(commandArguments(HPEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> httl(byte[] key, byte[]... fields) { + return new CommandObject<>(commandArguments(HTTL).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + + public final CommandObject> hpttl(byte[] key, byte[]... fields) { + return new CommandObject<>(commandArguments(HPTTL).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } + public final CommandObject> hpersist(String key, String... fields) { return new CommandObject<>(commandArguments(HPERSIST).key(key).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } + + public final CommandObject> hpersist(byte[] key, byte[]... fields) { + return new CommandObject<>(commandArguments(HPERSIST).key(key).add(fields.length).addObjects((Object[]) fields), + BuilderFactory.LONG_LIST); + } // Hash commands // Set commands diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 1a4b3010d5..66d64fa6eb 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -4656,6 +4656,84 @@ public long hstrlen(final byte[] key, final byte[] field) { return connection.executeCommand(commandObjects.hstrlen(key, field)); } + @Override + public List hexpire(byte[] key, long seconds, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpire(key, seconds, fields)); + } + + @Override + public List hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpire(key, seconds, condition, fields)); + } + + @Override + public List hpexpire(byte[] key, long milliseconds, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpire(key, milliseconds, fields)); + } + + @Override + public List hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpire(key, milliseconds, condition, fields)); + } + + @Override + public List hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, fields)); + } + + @Override + public List hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, condition, fields)); + } + + @Override + public List hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, fields)); + } + + @Override + public List hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); + } + + @Override + public List hexpireTime(byte[] key, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hexpireTime(key, fields)); + } + + @Override + public List hpexpireTime(byte[] key, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpexpireTime(key, fields)); + } + + @Override + public List httl(byte[] key, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.httl(key, fields)); + } + + @Override + public List hpttl(byte[] key, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpttl(key, fields)); + } + + @Override + public List hpersist(byte[] key, byte[]... fields) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.hpersist(key, fields)); + } + @Override public List xread(XReadParams xReadParams, Entry... streams) { checkIsInMultiOrPipeline(); diff --git a/src/main/java/redis/clients/jedis/PipeliningBase.java b/src/main/java/redis/clients/jedis/PipeliningBase.java index 8ce1375890..928126a704 100644 --- a/src/main/java/redis/clients/jedis/PipeliningBase.java +++ b/src/main/java/redis/clients/jedis/PipeliningBase.java @@ -2071,6 +2071,71 @@ public Response hstrlen(byte[] key, byte[] field) { return appendCommand(commandObjects.hstrlen(key, field)); } + @Override + public Response> hexpire(byte[] key, long seconds, byte[]... fields) { + return appendCommand(commandObjects.hexpire(key, seconds, fields)); + } + + @Override + public Response> hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields) { + return appendCommand(commandObjects.hexpire(key, seconds, condition, fields)); + } + + @Override + public Response> hpexpire(byte[] key, long milliseconds, byte[]... fields) { + return appendCommand(commandObjects.hpexpire(key, milliseconds, fields)); + } + + @Override + public Response> hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields) { + return appendCommand(commandObjects.hpexpire(key, milliseconds, condition, fields)); + } + + @Override + public Response> hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields) { + return appendCommand(commandObjects.hexpireAt(key, unixTimeSeconds, fields)); + } + + @Override + public Response> hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields) { + return appendCommand(commandObjects.hexpireAt(key, unixTimeSeconds, condition, fields)); + } + + @Override + public Response> hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields) { + return appendCommand(commandObjects.hpexpireAt(key, unixTimeMillis, fields)); + } + + @Override + public Response> hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields) { + return appendCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); + } + + @Override + public Response> hexpireTime(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.hexpireTime(key, fields)); + } + + @Override + public Response> hpexpireTime(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.hpexpireTime(key, fields)); + } + + @Override + public Response> httl(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.httl(key, fields)); + } + + @Override + public Response> hpttl(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.hpttl(key, fields)); + } + + @Override + public Response> hpersist(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.hpersist(key, fields)); + } + @Override public Response pfadd(byte[] key, byte[]... elements) { return appendCommand(commandObjects.pfadd(key, elements)); diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 27d1f81554..2d6e77fcf0 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -1641,6 +1641,46 @@ public List hpexpireAt(String key, long unixTimeMillis, ExpiryOption condi return executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); } + @Override + public List hexpire(byte[] key, long seconds, byte[]... fields) { + return executeCommand(commandObjects.hexpire(key, seconds, fields)); + } + + @Override + public List hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields) { + return executeCommand(commandObjects.hexpire(key, seconds, condition, fields)); + } + + @Override + public List hpexpire(byte[] key, long milliseconds, byte[]... fields) { + return executeCommand(commandObjects.hpexpire(key, milliseconds, fields)); + } + + @Override + public List hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields) { + return executeCommand(commandObjects.hpexpire(key, milliseconds, condition, fields)); + } + + @Override + public List hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields) { + return executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, fields)); + } + + @Override + public List hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields) { + return executeCommand(commandObjects.hexpireAt(key, unixTimeSeconds, condition, fields)); + } + + @Override + public List hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields) { + return executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, fields)); + } + + @Override + public List hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields) { + return executeCommand(commandObjects.hpexpireAt(key, unixTimeMillis, condition, fields)); + } + @Override public List hexpireTime(String key, String... fields) { return executeCommand(commandObjects.hexpireTime(key, fields)); @@ -1661,10 +1701,35 @@ public List hpttl(String key, String... fields) { return executeCommand(commandObjects.hpttl(key, fields)); } + @Override + public List hexpireTime(byte[] key, byte[]... fields) { + return executeCommand(commandObjects.hexpireTime(key, fields)); + } + + @Override + public List hpexpireTime(byte[] key, byte[]... fields) { + return executeCommand(commandObjects.hpexpireTime(key, fields)); + } + + @Override + public List httl(byte[] key, byte[]... fields) { + return executeCommand(commandObjects.httl(key, fields)); + } + + @Override + public List hpttl(byte[] key, byte[]... fields) { + return executeCommand(commandObjects.hpttl(key, fields)); + } + @Override public List hpersist(String key, String... fields) { return executeCommand(commandObjects.hpersist(key, fields)); } + + @Override + public List hpersist(byte[] key, byte[]... fields) { + return executeCommand(commandObjects.hpersist(key, fields)); + } // Hash commands // Set commands diff --git a/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java index 15a462c9b7..f32eca202e 100644 --- a/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.Set; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -57,4 +58,137 @@ default ScanResult hscanNoValues(byte[] key, byte[] cursor) { long hstrlen(byte[] key, byte[] field); + /** + * Set expiry for hash field using relative time to expire (seconds). + * + * @param key hash + * @param seconds time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpire(byte[] key, long seconds, byte[]... fields); + + /** + * Set expiry for hash field using relative time to expire (seconds). + * + * @param key hash + * @param seconds time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields); + + /** + * Set expiry for hash field using relative time to expire (milliseconds). + * + * @param key hash + * @param milliseconds time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpire(byte[] key, long milliseconds, byte[]... fields); + + /** + * Set expiry for hash field using relative time to expire (milliseconds). + * + * @param key hash + * @param milliseconds time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (seconds). + * + * @param key hash + * @param unixTimeSeconds time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (seconds). + * + * @param key hash + * @param unixTimeSeconds time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (milliseconds). + * + * @param key hash + * @param unixTimeMillis time to expire + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields); + + /** + * Set expiry for hash field using an absolute Unix timestamp (milliseconds). + * + * @param key hash + * @param unixTimeMillis time to expire + * @param condition can be NX, XX, GT or LT + * @param fields + * @return integer-reply: 1 if the timeout was set, 0 otherwise + */ + List hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields); + + /** + * Returns the expiration time of a hash field as a Unix timestamp, in seconds. + * + * @param key hash + * @param fields + * @return Expiration Unix timestamp in seconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hexpireTime(byte[] key, byte[]... fields); + + /** + * Returns the expiration time of a hash field as a Unix timestamp, in milliseconds. + * + * @param key hash + * @param fields + * @return Expiration Unix timestamp in milliseconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hpexpireTime(byte[] key, byte[]... fields); + + /** + * Returns the TTL in seconds of a hash field. + * + * @param key hash + * @param fields + * @return TTL in seconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List httl(byte[] key, byte[]... fields); + + /** + * Returns the TTL in milliseconds of a hash field. + * + * @param key hash + * @param fields + * @return TTL in milliseconds; + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hpttl(byte[] key, byte[]... fields); + + /** + * Removes the expiration time for each specified field. + * + * @param key hash + * @param fields + * @return integer-reply: 1 if the expiration time was removed, + * or -1 if the field exists but has no associated expire or -2 if the field does not exist. + */ + List hpersist(byte[] key, byte[]... fields); } diff --git a/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java index cf104f7a33..e428e72a63 100644 --- a/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java @@ -5,6 +5,7 @@ import java.util.Set; import redis.clients.jedis.Response; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -58,4 +59,29 @@ default Response> hscanNoValues(byte[] key, byte[] cursor) { Response hstrlen(byte[] key, byte[] field); + Response> hexpire(byte[] key, long seconds, byte[]... fields); + + Response> hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields); + + Response> hpexpire(byte[] key, long milliseconds, byte[]... fields); + + Response> hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields); + + Response> hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields); + + Response> hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields); + + Response> hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields); + + Response> hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields); + + Response> hexpireTime(byte[] key, byte[]... fields); + + Response> hpexpireTime(byte[] key, byte[]... fields); + + Response> httl(byte[] key, byte[]... fields); + + Response> hpttl(byte[] key, byte[]... fields); + + Response> hpersist(byte[] key, byte[]... fields); } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java index 66f9061a2d..2cf047bb32 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java @@ -731,4 +731,78 @@ public void hpersist() { assertThat(jedis.httl("foo", "bar", "bare", "bared"), contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); } + + @Test + public void hexpireAndHttlBinary() { + long seconds = 20; + + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(0L, 2L), jedis.hexpire(bfoo, -1, ExpiryOption.NX, bbar1, bbar3)); + + assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), + contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hpexpireAndHpttlBinary() { + long millis = 20_000; + + jedis.hset(bfoo, bbar1, bcar); + assertEquals(asList(1L, -2L), jedis.hpexpire(bfoo, millis, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(2L, 0L), jedis.hpexpire(bfoo, -100, ExpiryOption.XX, bbar1, bbar3)); + + assertThat(jedis.hpttl(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hexpireAtAndExpireTimeBinary() { + long currSeconds = System.currentTimeMillis() / 1000; + long unixSeconds = currSeconds + 20; + + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpireAt(bfoo, unixSeconds, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(2L, 0L), jedis.hexpireAt(bfoo, currSeconds - 1, ExpiryOption.LT, bbar1, bbar3)); + + assertThat(jedis.hexpireTime(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + } + + @Test + public void hpexpireAtAndPexpireTimeBinary() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; + + jedis.hset(bfoo, bbar1, bcar); + assertEquals(asList(1L, -2L), jedis.hpexpireAt(bfoo, unixMillis - 100, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(1L, 0L), jedis.hpexpireAt(bfoo, unixMillis, ExpiryOption.GT, bbar1, bbar3)); + + assertThat(jedis.hpexpireTime(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hpersistBinary() { + long seconds = 20; + + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds, bbar1, bbar3)); + + assertEquals(asList(1L, -1L, -2L), jedis.hpersist(bfoo, bbar1, bbar2, bbar3)); + + assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java index 1909423bab..081f5c1f64 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java @@ -694,4 +694,78 @@ public void hpersist() { assertThat(jedis.httl("foo", "bar", "bare", "bared"), contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); } + + @Test + public void hexpireAndHttlBinary() { + long seconds = 20; + + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(0L, 2L), jedis.hexpire(bfoo, -1, ExpiryOption.NX, bbar1, bbar3)); + + assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), + contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hpexpireAndHpttlBinary() { + long millis = 20_000; + + jedis.hset(bfoo, bbar1, bcar); + assertEquals(asList(1L, -2L), jedis.hpexpire(bfoo, millis, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(2L, 0L), jedis.hpexpire(bfoo, -100, ExpiryOption.XX, bbar1, bbar3)); + + assertThat(jedis.hpttl(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hexpireAtAndExpireTimeBinary() { + long currSeconds = System.currentTimeMillis() / 1000; + long unixSeconds = currSeconds + 20; + + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpireAt(bfoo, unixSeconds, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(2L, 0L), jedis.hexpireAt(bfoo, currSeconds - 1, ExpiryOption.LT, bbar1, bbar3)); + + assertThat(jedis.hexpireTime(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + } + + @Test + public void hpexpireAtAndPexpireTimeBinary() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; + + jedis.hset(bfoo, bbar1, bcar); + assertEquals(asList(1L, -2L), jedis.hpexpireAt(bfoo, unixMillis - 100, bbar1, bbar3)); + + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(1L, 0L), jedis.hpexpireAt(bfoo, unixMillis, ExpiryOption.GT, bbar1, bbar3)); + + assertThat(jedis.hpexpireTime(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hpersistBinary() { + long seconds = 20; + + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds, bbar1, bbar3)); + + assertEquals(asList(1L, -1L, -2L), jedis.hpersist(bfoo, bbar1, bbar2, bbar3)); + + assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java new file mode 100644 index 0000000000..a9e6f5547e --- /dev/null +++ b/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java @@ -0,0 +1,29 @@ +package redis.clients.jedis.commands.unified.cluster; + +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.commands.unified.HashesCommandsTestBase; + +@RunWith(Parameterized.class) +public class ClusterHashesCommandsTest extends HashesCommandsTestBase { + + public ClusterHashesCommandsTest(RedisProtocol protocol) { + super(protocol); + } + + @Before + public void setUp() { + jedis = ClusterCommandsTestHelper.getCleanCluster(protocol); + jedis.configSet("hash-max-listpack-entries", "0"); // TODO: remove + } + + @After + public void tearDown() { + jedis.close(); + ClusterCommandsTestHelper.clearClusterData(); + } + +} diff --git a/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java b/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java index fe656d95f9..1ea0d0b3c2 100644 --- a/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseHashCommandsTest.java @@ -20,6 +20,12 @@ public class PipeliningBaseHashCommandsTest extends PipeliningBaseMockedTestBase { + private final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; + + private final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A }; + private final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B }; + private final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C }; + @Test public void testHdel() { when(commandObjects.hdel("key", "field1", "field2")).thenReturn(longCommandObject); @@ -660,4 +666,159 @@ public void hpersist() { assertThat(listLongCommandObject, in(commands)); } + @Test + public void hexpireBinary() { + byte[] key = bfoo; + long seconds = 100; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hexpire(key, seconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpire(key, seconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireConditionBinary() { + byte[] key = bfoo; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hexpire(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpire(key, seconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpexpire(key, milliseconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpire(key, milliseconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireConditionBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpexpire(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpire(key, milliseconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireAtBinary() { + byte[] key = bfoo; + long seconds = 100; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hexpireAt(key, seconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpireAt(key, seconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireAtConditionBinary() { + byte[] key = bfoo; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hexpireAt(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpireAt(key, seconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireAtBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpexpireAt(key, milliseconds, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpireAt(key, milliseconds, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireAtConditionBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpexpireAt(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpireAt(key, milliseconds, condition, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hexpireTimeBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hexpireTime(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hexpireTime(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpexpireTimeBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpexpireTime(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpexpireTime(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void httlBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.httl(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.httl(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpttlBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpttl(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpttl(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + + @Test + public void hpersistBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + + when(commandObjects.hpersist(key, fields)).thenReturn(listLongCommandObject); + + assertThat(pipeliningBase.hpersist(key, fields), is(predefinedResponse)); + assertThat(listLongCommandObject, in(commands)); + } + } diff --git a/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java b/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java index 25e81a9b8e..d2dc8d8892 100644 --- a/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisHashCommandsTest.java @@ -23,6 +23,12 @@ public class UnifiedJedisHashCommandsTest extends UnifiedJedisMockedTestBase { + private final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; + + private final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A }; + private final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B }; + private final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C }; + @Test public void testHdel() { String key = "hashKey"; @@ -974,4 +980,211 @@ public void hpersist() { verify(commandObjects).hpersist(key, fields); } + @Test + public void hexpireBinary() { + byte[] key = bfoo; + long seconds = 100; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpire(key, seconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpire(key, seconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpire(key, seconds, fields); + } + + @Test + public void hexpireConditionBinary() { + byte[] key = bfoo; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpire(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpire(key, seconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpire(key, seconds, condition, fields); + } + + @Test + public void hpexpireBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 100L, 200L, 300L ); + + when(commandObjects.hpexpire(key, milliseconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpire(key, milliseconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpire(key, milliseconds, fields); + } + + @Test + public void hpexpireConditionBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 100L, 200L, 300L ); + + when(commandObjects.hpexpire(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpire(key, milliseconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpire(key, milliseconds, condition, fields); + } + + @Test + public void hexpireAtBinary() { + byte[] key = bfoo; + long seconds = 100; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpireAt(key, seconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpireAt(key, seconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpireAt(key, seconds, fields); + } + + @Test + public void hexpireAtConditionBinary() { + byte[] key = bfoo; + long seconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hexpireAt(key, seconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpireAt(key, seconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpireAt(key, seconds, condition, fields); + } + + @Test + public void hpexpireAtBinary() { + byte[] key = bfoo; + long milliseconds = 10000; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hpexpireAt(key, milliseconds, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpireAt(key, milliseconds, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpireAt(key, milliseconds, fields); + } + + @Test + public void hpexpireAtConditionBinary() { + byte[] key = bfoo; + long milliseconds = 100; + ExpiryOption condition = mock(ExpiryOption.class); + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hpexpireAt(key, milliseconds, condition, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpireAt(key, milliseconds, condition, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpireAt(key, milliseconds, condition, fields); + } + + @Test + public void hexpireTimeBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 10L, 20L, 30L ); + + when(commandObjects.hexpireTime(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hexpireTime(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hexpireTime(key, fields); + } + + @Test + public void hpexpireTimeBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1000L, 2000L, 3000L ); + + when(commandObjects.hpexpireTime(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpexpireTime(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpexpireTime(key, fields); + } + + @Test + public void httlBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 10L, 20L, 30L ); + + when(commandObjects.httl(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.httl(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).httl(key, fields); + } + + @Test + public void hpttlBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1000L, 2000L, 3000L ); + + when(commandObjects.hpttl(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpttl(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpttl(key, fields); + } + + @Test + public void hpersistBinary() { + byte[] key = bfoo; + byte[][] fields = { bbar1, bbar2, bbar3 }; + List expected = asList( 1L, 2L, 3L ); + + when(commandObjects.hpersist(key, fields)).thenReturn(listLongCommandObject); + when(commandExecutor.executeCommand(listLongCommandObject)).thenReturn(expected); + + assertThat(jedis.hpersist(key, fields), equalTo(expected)); + + verify(commandExecutor).executeCommand(listLongCommandObject); + verify(commandObjects).hpersist(key, fields); + } + } From e73afee1ffe2b7cb84fbc94e22fb45a267a175df Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Mon, 6 May 2024 16:10:17 +0600 Subject: [PATCH 3/8] Test new hash commands in CommandObjects --- .../CommandObjectsHashCommandsTest.java | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java index b025b85440..f29a2ca8cf 100644 --- a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java @@ -1,5 +1,6 @@ package redis.clients.jedis.commands.commandobjects; +import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.anyOf; @@ -7,6 +8,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.everyItem; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.lessThanOrEqualTo; @@ -19,6 +21,7 @@ import org.junit.Test; import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; @@ -27,8 +30,19 @@ */ public class CommandObjectsHashCommandsTest extends CommandObjectsStandaloneTestBase { + private final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; + private final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C }; + + private final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A }; + private final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B }; + private final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C }; + public CommandObjectsHashCommandsTest(RedisProtocol protocol) { super(protocol); + // TODO: remove --> + setUp(); + exec(commandObjects.configSet("hash-max-listpack-entries", "0")); + // <-- TODO: remove } @Test @@ -402,4 +416,152 @@ public void testHashStrlen() { Long strlenNonExistingFieldBinary = exec(commandObjects.hstrlen(bkey, "nonExistingField".getBytes())); assertThat(strlenNonExistingFieldBinary, equalTo(0L)); } + + @Test + public void hexpireAndHttl() { + long seconds = 20; + + exec(commandObjects.hset("foo", "bar", "car")); + exec(commandObjects.hset("foo", "bare", "care")); + assertThat(exec(commandObjects.hexpire("foo", seconds, "bar", "bared")), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset("foo", "bared", "cared")); + assertThat(exec(commandObjects.hexpire("foo", -1, ExpiryOption.NX, "bar", "bared")), equalTo(asList(0L, 2L))); + + assertThat(exec(commandObjects.httl("foo", "bar", "bare", "bared")), + contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hpexpireAndHpttl() { + long millis = 20_000; + + exec(commandObjects.hset("foo", "bar", "car")); + assertThat(exec(commandObjects.hpexpire("foo", millis, "bar", "bared")), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset("foo", "bared", "cared")); + assertThat(exec(commandObjects.hpexpire("foo", -100, ExpiryOption.XX, "bar", "bared")), equalTo(asList(2L, 0L))); + + assertThat(exec(commandObjects.hpttl("foo", "bar", "bare", "bared")), + contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hexpireAtAndExpireTime() { + long currSeconds = System.currentTimeMillis() / 1000; + long unixSeconds = currSeconds + 20; + + exec(commandObjects.hset("foo", "bar", "car")); + exec(commandObjects.hset("foo", "bare", "care")); + assertThat(exec(commandObjects.hexpireAt("foo", unixSeconds, "bar", "bared")), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset("foo", "bared", "cared")); + assertThat(exec(commandObjects.hexpireAt("foo", currSeconds - 1, ExpiryOption.LT, "bar", "bared")), equalTo(asList(2L, 0L))); + + assertThat(exec(commandObjects.hexpireTime("foo", "bar", "bare", "bared")), + contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + } + + @Test + public void hpexpireAtAndPexpireTime() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; + + exec(commandObjects.hset("foo", "bar", "car")); + assertThat(exec(commandObjects.hpexpireAt("foo", unixMillis - 100, "bar", "bared")), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset("foo", "bared", "cared")); + assertThat(exec(commandObjects.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")), equalTo(asList(1L, 0L))); + + assertThat(exec(commandObjects.hpexpireTime("foo", "bar", "bare", "bared")), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hpersist() { + long seconds = 20; + + exec(commandObjects.hset("foo", "bar", "car")); + exec(commandObjects.hset("foo", "bare", "care")); + assertThat(exec(commandObjects.hexpire("foo", seconds, "bar", "bared")), equalTo(asList(1L, -2L))); + + assertThat(exec(commandObjects.hpersist("foo", "bar", "bare", "bared")), equalTo(asList(1L, -1L, -2L))); + + assertThat(exec(commandObjects.httl("foo", "bar", "bare", "bared")), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hexpireAndHttlBinary() { + long seconds = 20; + + exec(commandObjects.hset(bfoo, bbar1, bcar)); + exec(commandObjects.hset(bfoo, bbar2, bcar)); + assertThat(exec(commandObjects.hexpire(bfoo, seconds, bbar1, bbar3)), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset(bfoo, bbar3, bcar)); + assertThat(exec(commandObjects.hexpire(bfoo, -1, ExpiryOption.NX, bbar1, bbar3)), equalTo(asList(0L, 2L))); + + assertThat(exec(commandObjects.httl(bfoo, bbar1, bbar2, bbar3)), + contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + } + + @Test + public void hpexpireAndHpttlBinary() { + long millis = 20_000; + + exec(commandObjects.hset(bfoo, bbar1, bcar)); + assertThat(exec(commandObjects.hpexpire(bfoo, millis, bbar1, bbar3)), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset(bfoo, bbar3, bcar)); + assertThat(exec(commandObjects.hpexpire(bfoo, -100, ExpiryOption.XX, bbar1, bbar3)), equalTo(asList(2L, 0L))); + + assertThat(exec(commandObjects.hpttl(bfoo, bbar1, bbar2, bbar3)), + contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hexpireAtAndExpireTimeBinary() { + long currSeconds = System.currentTimeMillis() / 1000; + long unixSeconds = currSeconds + 20; + + exec(commandObjects.hset(bfoo, bbar1, bcar)); + exec(commandObjects.hset(bfoo, bbar2, bcar)); + assertThat(exec(commandObjects.hexpireAt(bfoo, unixSeconds, bbar1, bbar3)), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset(bfoo, bbar3, bcar)); + assertThat(exec(commandObjects.hexpireAt(bfoo, currSeconds - 1, ExpiryOption.LT, bbar1, bbar3)), equalTo(asList(2L, 0L))); + + assertThat(exec(commandObjects.hexpireTime(bfoo, bbar1, bbar2, bbar3)), + contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + } + + @Test + public void hpexpireAtAndPexpireTimeBinary() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; + + exec(commandObjects.hset(bfoo, bbar1, bcar)); + assertThat(exec(commandObjects.hpexpireAt(bfoo, unixMillis - 100, bbar1, bbar3)), equalTo(asList(1L, -2L))); + + exec(commandObjects.hset(bfoo, bbar3, bcar)); + assertThat(exec(commandObjects.hpexpireAt(bfoo, unixMillis, ExpiryOption.GT, bbar1, bbar3)), equalTo(asList(1L, 0L))); + + assertThat(exec(commandObjects.hpexpireTime(bfoo, bbar1, bbar2, bbar3)), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + } + + @Test + public void hpersistBinary() { + long seconds = 20; + + exec(commandObjects.hset(bfoo, bbar1, bcar)); + exec(commandObjects.hset(bfoo, bbar2, bcar)); + assertThat(exec(commandObjects.hexpire(bfoo, seconds, bbar1, bbar3)), equalTo(asList(1L, -2L))); + + assertThat(exec(commandObjects.hpersist(bfoo, bbar1, bbar2, bbar3)), equalTo(asList(1L, -1L, -2L))); + + assertThat(exec(commandObjects.httl(bfoo, bbar1, bbar2, bbar3)), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } } From a035eeea24be51e3868bc60e8d46559fc73cf565 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 12 May 2024 13:01:31 +0600 Subject: [PATCH 4/8] Hash expiration is now supported with listpack --- .../commandobjects/CommandObjectsHashCommandsTest.java | 4 ---- .../clients/jedis/commands/jedis/HashesCommandsTest.java | 9 --------- .../unified/cluster/ClusterHashesCommandsTest.java | 1 - .../unified/pooled/PooledHashesCommandsTest.java | 1 - 4 files changed, 15 deletions(-) diff --git a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java index f29a2ca8cf..883465c846 100644 --- a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java @@ -39,10 +39,6 @@ public class CommandObjectsHashCommandsTest extends CommandObjectsStandaloneTest public CommandObjectsHashCommandsTest(RedisProtocol protocol) { super(protocol); - // TODO: remove --> - setUp(); - exec(commandObjects.configSet("hash-max-listpack-entries", "0")); - // <-- TODO: remove } @Test diff --git a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java index 2cf047bb32..6702897cb8 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java @@ -56,15 +56,6 @@ public HashesCommandsTest(RedisProtocol protocol) { super(protocol); } - // TODO: remove - @org.junit.BeforeClass - public static void prepare() { - try (redis.clients.jedis.Jedis j = new redis.clients.jedis.Jedis(hnp)) { - j.auth("foobared"); - j.configSet("hash-max-listpack-entries", "0"); - } - } - @Test public void hset() { assertEquals(1, jedis.hset("foo", "bar", "car")); diff --git a/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java index 569f1c75fd..a5590a2730 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterHashesCommandsTest.java @@ -17,7 +17,6 @@ public ClusterHashesCommandsTest(RedisProtocol protocol) { @Before public void setUp() { jedis = ClusterCommandsTestHelper.getCleanCluster(protocol); - jedis.configSet("hash-max-listpack-entries", "0"); // TODO: remove } @After diff --git a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java index 2be4582cd7..bb5741d967 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledHashesCommandsTest.java @@ -19,7 +19,6 @@ public PooledHashesCommandsTest(RedisProtocol protocol) { public void setUp() { jedis = PooledCommandsTestHelper.getPooled(protocol); PooledCommandsTestHelper.clearData(); - jedis.configSet("hash-max-listpack-entries", "0"); // TODO: remove } @After From 3c39aaa3007f06c04673c536a7246c2a49094366 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 19 May 2024 22:12:29 +0600 Subject: [PATCH 5/8] Address constant FIELDS argument in Hash field expiration commands --- .../redis/clients/jedis/CommandObjects.java | 80 +++++++++---------- .../java/redis/clients/jedis/Protocol.java | 4 +- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index ab048d50b4..bbe24e4c21 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -1157,133 +1157,133 @@ public final CommandObject hstrlen(byte[] key, byte[] field) { } public final CommandObject> hexpire(String key, long seconds, String... fields) { - return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpire(String key, long seconds, ExpiryOption condition, String... fields) { - return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpire(String key, long milliseconds, String... fields) { - return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpire(String key, long milliseconds, ExpiryOption condition, String... fields) { - return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireAt(String key, long unixTimeSeconds, String... fields) { return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireAt(String key, long unixTimeSeconds, ExpiryOption condition, String... fields) { return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds).add(condition) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpireAt(String key, long unixTimeMillis, String... fields) { return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpireAt(String key, long unixTimeMillis, ExpiryOption condition, String... fields) { return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis).add(condition) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpire(byte[] key, long seconds, byte[]... fields) { return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields) { return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpire(byte[] key, long milliseconds, byte[]... fields) { return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields) { return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition).add(fields.length) - .addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields) { return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireAt(byte[] key, long unixTimeSeconds, ExpiryOption condition, byte[]... fields) { return new CommandObject<>(commandArguments(HEXPIREAT).key(key).add(unixTimeSeconds).add(condition) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpireAt(byte[] key, long unixTimeMillis, byte[]... fields) { return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpireAt(byte[] key, long unixTimeMillis, ExpiryOption condition, byte[]... fields) { return new CommandObject<>(commandArguments(HPEXPIREAT).key(key).add(unixTimeMillis).add(condition) - .add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireTime(String key, String... fields) { - return new CommandObject<>(commandArguments(HEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HEXPIRETIME).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpireTime(String key, String... fields) { - return new CommandObject<>(commandArguments(HPEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPEXPIRETIME).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> httl(String key, String... fields) { - return new CommandObject<>(commandArguments(HTTL).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HTTL).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpttl(String key, String... fields) { - return new CommandObject<>(commandArguments(HPTTL).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPTTL).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireTime(byte[] key, byte[]... fields) { - return new CommandObject<>(commandArguments(HEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HEXPIRETIME).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpireTime(byte[] key, byte[]... fields) { - return new CommandObject<>(commandArguments(HPEXPIRETIME).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPEXPIRETIME).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> httl(byte[] key, byte[]... fields) { - return new CommandObject<>(commandArguments(HTTL).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HTTL).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpttl(byte[] key, byte[]... fields) { - return new CommandObject<>(commandArguments(HPTTL).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPTTL).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpersist(String key, String... fields) { - return new CommandObject<>(commandArguments(HPERSIST).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPERSIST).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpersist(byte[] key, byte[]... fields) { - return new CommandObject<>(commandArguments(HPERSIST).key(key).add(fields.length).addObjects((Object[]) fields), - BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPERSIST).key(key) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } // Hash commands diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 093a3463f7..448bd7ff12 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -300,8 +300,8 @@ public static enum Keyword implements Rawable { REV, WITHCOORD, WITHDIST, WITHHASH, ANY, FROMMEMBER, FROMLONLAT, BYRADIUS, BYBOX, BYLEX, BYSCORE, STOREDIST, TO, FORCE, TIMEOUT, DB, UNLOAD, ABORT, IDX, MINMATCHLEN, WITHMATCHLEN, FULL, DELETE, LIBRARYNAME, WITHCODE, DESCRIPTION, GETKEYS, GETKEYSANDFLAGS, DOCS, FILTERBY, DUMP, - MODULE, ACLCAT, PATTERN, DOCTOR, LATEST, HISTORY, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, ARGS, RANK, - NOW, VERSION, ADDR, SKIPME, USER, LADDR, + MODULE, ACLCAT, PATTERN, DOCTOR, LATEST, HISTORY, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, + ARGS, RANK, NOW, VERSION, ADDR, SKIPME, USER, LADDR, FIELDS, CHANNELS, NUMPAT, NUMSUB, SHARDCHANNELS, SHARDNUMSUB, NOVALUES, MAXAGE; private final byte[] raw; From 6a06ce86a304a07665b5d5173f2f3c9c3fe89a6b Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 19 May 2024 23:05:49 +0600 Subject: [PATCH 6/8] Fix FIELDS place --- .../java/redis/clients/jedis/CommandObjects.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index bbe24e4c21..754c25cf35 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -1197,23 +1197,23 @@ public final CommandObject> hpexpireAt(String key, long unixTimeMilli } public final CommandObject> hexpire(byte[] key, long seconds, byte[]... fields) { - return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(fields.length) - .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpire(byte[] key, long seconds, ExpiryOption condition, byte[]... fields) { - return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition).add(fields.length) - .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HEXPIRE).key(key).add(seconds).add(condition) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpire(byte[] key, long milliseconds, byte[]... fields) { - return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(fields.length) - .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hpexpire(byte[] key, long milliseconds, ExpiryOption condition, byte[]... fields) { - return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition).add(fields.length) - .add(FIELDS).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(HPEXPIRE).key(key).add(milliseconds).add(condition) + .add(FIELDS).add(fields.length).addObjects((Object[]) fields), BuilderFactory.LONG_LIST); } public final CommandObject> hexpireAt(byte[] key, long unixTimeSeconds, byte[]... fields) { From d06c8823e97c9b5d55763a840d4edec98c961f02 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:54:07 +0600 Subject: [PATCH 7/8] Back to using Redis unstable branch --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fc6935486c..1800f00d7e 100644 --- a/Makefile +++ b/Makefile @@ -527,7 +527,7 @@ mvn-release: system-setup: sudo apt install -y gcc g++ - [ ! -e redis-git ] && git clone https://github.com/redis/redis.git --branch hash-field-expiry-integ --single-branch redis-git || true + [ ! -e redis-git ] && git clone https://github.com/redis/redis.git --branch unstable --single-branch redis-git || true $(MAKE) -C redis-git clean $(MAKE) -C redis-git From 03f9d992c68a7f0705df4b7e81ee7a0250af2eb9 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:12:29 +0600 Subject: [PATCH 8/8] Modify HFE tests due to changes in server --- .../CommandObjectsHashCommandsTest.java | 142 +++++++++-------- .../commands/jedis/HashesCommandsTest.java | 143 ++++++++++-------- .../unified/HashesCommandsTestBase.java | 143 ++++++++++-------- 3 files changed, 233 insertions(+), 195 deletions(-) diff --git a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java index 883465c846..a8de3122ab 100644 --- a/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsHashCommandsTest.java @@ -4,10 +4,12 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.everyItem; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasSize; @@ -415,121 +417,117 @@ public void testHashStrlen() { @Test public void hexpireAndHttl() { - long seconds = 20; + long seconds1 = 20; + long seconds2 = 10; exec(commandObjects.hset("foo", "bar", "car")); exec(commandObjects.hset("foo", "bare", "care")); - assertThat(exec(commandObjects.hexpire("foo", seconds, "bar", "bared")), equalTo(asList(1L, -2L))); + assertThat(exec(commandObjects.hexpire("foo", seconds1, "bar", "bared")), equalTo(asList(1L, -2L))); exec(commandObjects.hset("foo", "bared", "cared")); - assertThat(exec(commandObjects.hexpire("foo", -1, ExpiryOption.NX, "bar", "bared")), equalTo(asList(0L, 2L))); + assertThat(exec(commandObjects.hexpire("foo", seconds2, ExpiryOption.NX, "bar", "bared")), equalTo(asList(0L, 1L))); assertThat(exec(commandObjects.httl("foo", "bar", "bare", "bared")), - contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + contains(greaterThanOrEqualTo(seconds1 - 1), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hpexpireAndHpttl() { - long millis = 20_000; + public void hexpireAndHttlBinary() { + long seconds1 = 20; + long seconds2 = 10; - exec(commandObjects.hset("foo", "bar", "car")); - assertThat(exec(commandObjects.hpexpire("foo", millis, "bar", "bared")), equalTo(asList(1L, -2L))); + exec(commandObjects.hset(bfoo, bbar1, bcar)); + exec(commandObjects.hset(bfoo, bbar2, bcar)); + assertThat(exec(commandObjects.hexpire(bfoo, seconds1, bbar1, bbar3)), equalTo(asList(1L, -2L))); - exec(commandObjects.hset("foo", "bared", "cared")); - assertThat(exec(commandObjects.hpexpire("foo", -100, ExpiryOption.XX, "bar", "bared")), equalTo(asList(2L, 0L))); + exec(commandObjects.hset(bfoo, bbar3, bcar)); + assertThat(exec(commandObjects.hexpire(bfoo, seconds2, ExpiryOption.NX, bbar1, bbar3)), equalTo(asList(0L, 1L))); - assertThat(exec(commandObjects.hpttl("foo", "bar", "bare", "bared")), - contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + assertThat(exec(commandObjects.httl(bfoo, bbar1, bbar2, bbar3)), + contains(greaterThanOrEqualTo(seconds1 - 1), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAtAndExpireTime() { - long currSeconds = System.currentTimeMillis() / 1000; - long unixSeconds = currSeconds + 20; + public void hpexpireAndHpttl() { + long millis1 = 20_000; + long millis2 = 10_000; exec(commandObjects.hset("foo", "bar", "car")); - exec(commandObjects.hset("foo", "bare", "care")); - assertThat(exec(commandObjects.hexpireAt("foo", unixSeconds, "bar", "bared")), equalTo(asList(1L, -2L))); + assertThat(exec(commandObjects.hpexpire("foo", millis1, "bar", "bared")), equalTo(asList(1L, -2L))); exec(commandObjects.hset("foo", "bared", "cared")); - assertThat(exec(commandObjects.hexpireAt("foo", currSeconds - 1, ExpiryOption.LT, "bar", "bared")), equalTo(asList(2L, 0L))); + assertThat(exec(commandObjects.hpexpire("foo", millis2, ExpiryOption.XX, "bar", "bared")), equalTo(asList(1L, 0L))); - assertThat(exec(commandObjects.hexpireTime("foo", "bar", "bare", "bared")), - contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + assertThat(exec(commandObjects.hpttl("foo", "bar", "bare", "bared")), + contains(both(lessThanOrEqualTo(millis2)).and(greaterThan(millis2 - 10)), equalTo(-2L), equalTo(-1L))); } @Test - public void hpexpireAtAndPexpireTime() { - long currMillis = System.currentTimeMillis(); - long unixMillis = currMillis + 20_000; + public void hpexpireAndHpttlBinary() { + long millis1 = 20_000; + long millis2 = 10_000; - exec(commandObjects.hset("foo", "bar", "car")); - assertThat(exec(commandObjects.hpexpireAt("foo", unixMillis - 100, "bar", "bared")), equalTo(asList(1L, -2L))); + exec(commandObjects.hset(bfoo, bbar1, bcar)); + assertThat(exec(commandObjects.hpexpire(bfoo, millis1, bbar1, bbar3)), equalTo(asList(1L, -2L))); - exec(commandObjects.hset("foo", "bared", "cared")); - assertThat(exec(commandObjects.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")), equalTo(asList(1L, 0L))); + exec(commandObjects.hset(bfoo, bbar3, bcar)); + assertThat(exec(commandObjects.hpexpire(bfoo, millis2, ExpiryOption.XX, bbar1, bbar3)), equalTo(asList(1L, 0L))); - assertThat(exec(commandObjects.hpexpireTime("foo", "bar", "bare", "bared")), - contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + assertThat(exec(commandObjects.hpttl(bfoo, bbar1, bbar2, bbar3)), + contains(both(lessThanOrEqualTo(millis2)).and(greaterThan(millis2 - 10)), equalTo(-2L), equalTo(-1L))); } @Test - public void hpersist() { - long seconds = 20; + public void hexpireAtAndExpireTime() { + long currSeconds = System.currentTimeMillis() / 1000; + long seconds1 = currSeconds + 20; + long seconds2 = currSeconds + 10; exec(commandObjects.hset("foo", "bar", "car")); exec(commandObjects.hset("foo", "bare", "care")); - assertThat(exec(commandObjects.hexpire("foo", seconds, "bar", "bared")), equalTo(asList(1L, -2L))); + assertThat(exec(commandObjects.hexpireAt("foo", seconds1, "bar", "bared")), equalTo(asList(1L, -2L))); - assertThat(exec(commandObjects.hpersist("foo", "bar", "bare", "bared")), equalTo(asList(1L, -1L, -2L))); + exec(commandObjects.hset("foo", "bared", "cared")); + assertThat(exec(commandObjects.hexpireAt("foo", seconds2, ExpiryOption.LT, "bar", "bared")), equalTo(asList(1L, 1L))); - assertThat(exec(commandObjects.httl("foo", "bar", "bare", "bared")), - contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + assertThat(exec(commandObjects.hexpireTime("foo", "bar", "bare", "bared")), + contains(both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAndHttlBinary() { - long seconds = 20; + public void hexpireAtAndExpireTimeBinary() { + long currSeconds = System.currentTimeMillis() / 1000; + long seconds1 = currSeconds + 20; + long seconds2 = currSeconds + 10; exec(commandObjects.hset(bfoo, bbar1, bcar)); exec(commandObjects.hset(bfoo, bbar2, bcar)); - assertThat(exec(commandObjects.hexpire(bfoo, seconds, bbar1, bbar3)), equalTo(asList(1L, -2L))); - - exec(commandObjects.hset(bfoo, bbar3, bcar)); - assertThat(exec(commandObjects.hexpire(bfoo, -1, ExpiryOption.NX, bbar1, bbar3)), equalTo(asList(0L, 2L))); - - assertThat(exec(commandObjects.httl(bfoo, bbar1, bbar2, bbar3)), - contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); - } - - @Test - public void hpexpireAndHpttlBinary() { - long millis = 20_000; - - exec(commandObjects.hset(bfoo, bbar1, bcar)); - assertThat(exec(commandObjects.hpexpire(bfoo, millis, bbar1, bbar3)), equalTo(asList(1L, -2L))); + assertThat(exec(commandObjects.hexpireAt(bfoo, seconds1, bbar1, bbar3)), equalTo(asList(1L, -2L))); exec(commandObjects.hset(bfoo, bbar3, bcar)); - assertThat(exec(commandObjects.hpexpire(bfoo, -100, ExpiryOption.XX, bbar1, bbar3)), equalTo(asList(2L, 0L))); + assertThat(exec(commandObjects.hexpireAt(bfoo, seconds2, ExpiryOption.LT, bbar1, bbar3)), equalTo(asList(1L, 1L))); - assertThat(exec(commandObjects.hpttl(bfoo, bbar1, bbar2, bbar3)), - contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + assertThat(exec(commandObjects.hexpireTime(bfoo, bbar1, bbar2, bbar3)), + contains(both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAtAndExpireTimeBinary() { - long currSeconds = System.currentTimeMillis() / 1000; - long unixSeconds = currSeconds + 20; + public void hpexpireAtAndPexpireTime() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; - exec(commandObjects.hset(bfoo, bbar1, bcar)); - exec(commandObjects.hset(bfoo, bbar2, bcar)); - assertThat(exec(commandObjects.hexpireAt(bfoo, unixSeconds, bbar1, bbar3)), equalTo(asList(1L, -2L))); + exec(commandObjects.hset("foo", "bar", "car")); + assertThat(exec(commandObjects.hpexpireAt("foo", unixMillis - 100, "bar", "bared")), equalTo(asList(1L, -2L))); - exec(commandObjects.hset(bfoo, bbar3, bcar)); - assertThat(exec(commandObjects.hexpireAt(bfoo, currSeconds - 1, ExpiryOption.LT, bbar1, bbar3)), equalTo(asList(2L, 0L))); + exec(commandObjects.hset("foo", "bared", "cared")); + assertThat(exec(commandObjects.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")), equalTo(asList(1L, 0L))); - assertThat(exec(commandObjects.hexpireTime(bfoo, bbar1, bbar2, bbar3)), - contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + assertThat(exec(commandObjects.hpexpireTime("foo", "bar", "bare", "bared")), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); } @Test @@ -547,6 +545,20 @@ public void hpexpireAtAndPexpireTimeBinary() { contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); } + @Test + public void hpersist() { + long seconds = 20; + + exec(commandObjects.hset("foo", "bar", "car")); + exec(commandObjects.hset("foo", "bare", "care")); + assertThat(exec(commandObjects.hexpire("foo", seconds, "bar", "bared")), equalTo(asList(1L, -2L))); + + assertThat(exec(commandObjects.hpersist("foo", "bar", "bare", "bared")), equalTo(asList(1L, -1L, -2L))); + + assertThat(exec(commandObjects.httl("foo", "bar", "bare", "bared")), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } + @Test public void hpersistBinary() { long seconds = 20; diff --git a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java index 6702897cb8..88ca543fc4 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java @@ -3,10 +3,13 @@ import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -651,121 +654,117 @@ public void hrandfield() { @Test public void hexpireAndHttl() { - long seconds = 20; + long seconds1 = 20; + long seconds2 = 10; jedis.hset("foo", "bar", "car"); jedis.hset("foo", "bare", "care"); - assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds1, "bar", "bared")); jedis.hset("foo", "bared", "cared"); - assertEquals(asList(0L, 2L), jedis.hexpire("foo", -1, ExpiryOption.NX, "bar", "bared")); + assertEquals(asList(0L, 1L), jedis.hexpire("foo", seconds2, ExpiryOption.NX, "bar", "bared")); assertThat(jedis.httl("foo", "bar", "bare", "bared"), - contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + contains(greaterThanOrEqualTo(seconds1 - 1), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hpexpireAndHpttl() { - long millis = 20_000; + public void hexpireAndHttlBinary() { + long seconds1 = 20; + long seconds2 = 10; - jedis.hset("foo", "bar", "car"); - assertEquals(asList(1L, -2L), jedis.hpexpire("foo", millis, "bar", "bared")); + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds1, bbar1, bbar3)); - jedis.hset("foo", "bared", "cared"); - assertEquals(asList(2L, 0L), jedis.hpexpire("foo", -100, ExpiryOption.XX, "bar", "bared")); + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(0L, 1L), jedis.hexpire(bfoo, seconds2, ExpiryOption.NX, bbar1, bbar3)); - assertThat(jedis.hpttl("foo", "bar", "bare", "bared"), - contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), + contains(greaterThanOrEqualTo(seconds1 - 1), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAtAndExpireTime() { - long currSeconds = System.currentTimeMillis() / 1000; - long unixSeconds = currSeconds + 20; + public void hpexpireAndHpttl() { + long millis1 = 20_000; + long millis2 = 10_000; jedis.hset("foo", "bar", "car"); - jedis.hset("foo", "bare", "care"); - assertEquals(asList(1L, -2L), jedis.hexpireAt("foo", unixSeconds, "bar", "bared")); + assertEquals(asList(1L, -2L), jedis.hpexpire("foo", millis1, "bar", "bared")); jedis.hset("foo", "bared", "cared"); - assertEquals(asList(2L, 0L), jedis.hexpireAt("foo", currSeconds - 1, ExpiryOption.LT, "bar", "bared")); + assertEquals(asList(1L, 0L), jedis.hpexpire("foo", millis2, ExpiryOption.XX, "bar", "bared")); - assertThat(jedis.hexpireTime("foo", "bar", "bare", "bared"), - contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + assertThat(jedis.hpttl("foo", "bar", "bare", "bared"), + contains(both(lessThanOrEqualTo(millis2)).and(greaterThan(millis2 - 10)), equalTo(-2L), equalTo(-1L))); } @Test - public void hpexpireAtAndPexpireTime() { - long currMillis = System.currentTimeMillis(); - long unixMillis = currMillis + 20_000; + public void hpexpireAndHpttlBinary() { + long millis1 = 20_000; + long millis2 = 10_000; - jedis.hset("foo", "bar", "car"); - assertEquals(asList(1L, -2L), jedis.hpexpireAt("foo", unixMillis - 100, "bar", "bared")); + jedis.hset(bfoo, bbar1, bcar); + assertEquals(asList(1L, -2L), jedis.hpexpire(bfoo, millis1, bbar1, bbar3)); - jedis.hset("foo", "bared", "cared"); - assertEquals(asList(1L, 0L), jedis.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")); + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(1L, 0L), jedis.hpexpire(bfoo, millis2, ExpiryOption.XX, bbar1, bbar3)); - assertThat(jedis.hpexpireTime("foo", "bar", "bare", "bared"), - contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + assertThat(jedis.hpttl(bfoo, bbar1, bbar2, bbar3), + contains(both(lessThanOrEqualTo(millis2)).and(greaterThan(millis2 - 10)), equalTo(-2L), equalTo(-1L))); } @Test - public void hpersist() { - long seconds = 20; + public void hexpireAtAndExpireTime() { + long currSeconds = System.currentTimeMillis() / 1000; + long seconds1 = currSeconds + 20; + long seconds2 = currSeconds + 10; jedis.hset("foo", "bar", "car"); jedis.hset("foo", "bare", "care"); - assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + assertEquals(asList(1L, -2L), jedis.hexpireAt("foo", seconds1, "bar", "bared")); - assertEquals(asList(1L, -1L, -2L), jedis.hpersist("foo", "bar", "bare", "bared")); + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(1L, 1L), jedis.hexpireAt("foo", seconds2, ExpiryOption.LT, "bar", "bared")); - assertThat(jedis.httl("foo", "bar", "bare", "bared"), - contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + assertThat(jedis.hexpireTime("foo", "bar", "bare", "bared"), + contains(both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAndHttlBinary() { - long seconds = 20; + public void hexpireAtAndExpireTimeBinary() { + long currSeconds = System.currentTimeMillis() / 1000; + long seconds1 = currSeconds + 20; + long seconds2 = currSeconds + 10; jedis.hset(bfoo, bbar1, bcar); jedis.hset(bfoo, bbar2, bcar); - assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds, bbar1, bbar3)); - - jedis.hset(bfoo, bbar3, bcar); - assertEquals(asList(0L, 2L), jedis.hexpire(bfoo, -1, ExpiryOption.NX, bbar1, bbar3)); - - assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), - contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); - } - - @Test - public void hpexpireAndHpttlBinary() { - long millis = 20_000; - - jedis.hset(bfoo, bbar1, bcar); - assertEquals(asList(1L, -2L), jedis.hpexpire(bfoo, millis, bbar1, bbar3)); + assertEquals(asList(1L, -2L), jedis.hexpireAt(bfoo, seconds1, bbar1, bbar3)); jedis.hset(bfoo, bbar3, bcar); - assertEquals(asList(2L, 0L), jedis.hpexpire(bfoo, -100, ExpiryOption.XX, bbar1, bbar3)); + assertEquals(asList(1L, 1L), jedis.hexpireAt(bfoo, seconds2, ExpiryOption.LT, bbar1, bbar3)); - assertThat(jedis.hpttl(bfoo, bbar1, bbar2, bbar3), - contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + assertThat(jedis.hexpireTime(bfoo, bbar1, bbar2, bbar3), + contains(both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAtAndExpireTimeBinary() { - long currSeconds = System.currentTimeMillis() / 1000; - long unixSeconds = currSeconds + 20; + public void hpexpireAtAndPexpireTime() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; - jedis.hset(bfoo, bbar1, bcar); - jedis.hset(bfoo, bbar2, bcar); - assertEquals(asList(1L, -2L), jedis.hexpireAt(bfoo, unixSeconds, bbar1, bbar3)); + jedis.hset("foo", "bar", "car"); + assertEquals(asList(1L, -2L), jedis.hpexpireAt("foo", unixMillis - 100, "bar", "bared")); - jedis.hset(bfoo, bbar3, bcar); - assertEquals(asList(2L, 0L), jedis.hexpireAt(bfoo, currSeconds - 1, ExpiryOption.LT, bbar1, bbar3)); + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(1L, 0L), jedis.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")); - assertThat(jedis.hexpireTime(bfoo, bbar1, bbar2, bbar3), - contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + assertThat(jedis.hpexpireTime("foo", "bar", "bare", "bared"), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); } @Test @@ -783,6 +782,20 @@ public void hpexpireAtAndPexpireTimeBinary() { contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); } + @Test + public void hpersist() { + long seconds = 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + + assertEquals(asList(1L, -1L, -2L), jedis.hpersist("foo", "bar", "bare", "bared")); + + assertThat(jedis.httl("foo", "bar", "bare", "bared"), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } + @Test public void hpersistBinary() { long seconds = 20; diff --git a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java index 081f5c1f64..f84b0c2cc6 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java @@ -3,10 +3,13 @@ import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -623,121 +626,117 @@ public void hrandfield() { @Test public void hexpireAndHttl() { - long seconds = 20; + long seconds1 = 20; + long seconds2 = 10; jedis.hset("foo", "bar", "car"); jedis.hset("foo", "bare", "care"); - assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds1, "bar", "bared")); jedis.hset("foo", "bared", "cared"); - assertEquals(asList(0L, 2L), jedis.hexpire("foo", -1, ExpiryOption.NX, "bar", "bared")); + assertEquals(asList(0L, 1L), jedis.hexpire("foo", seconds2, ExpiryOption.NX, "bar", "bared")); assertThat(jedis.httl("foo", "bar", "bare", "bared"), - contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); + contains(greaterThanOrEqualTo(seconds1 - 1), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hpexpireAndHpttl() { - long millis = 20_000; + public void hexpireAndHttlBinary() { + long seconds1 = 20; + long seconds2 = 10; - jedis.hset("foo", "bar", "car"); - assertEquals(asList(1L, -2L), jedis.hpexpire("foo", millis, "bar", "bared")); + jedis.hset(bfoo, bbar1, bcar); + jedis.hset(bfoo, bbar2, bcar); + assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds1, bbar1, bbar3)); - jedis.hset("foo", "bared", "cared"); - assertEquals(asList(2L, 0L), jedis.hpexpire("foo", -100, ExpiryOption.XX, "bar", "bared")); + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(0L, 1L), jedis.hexpire(bfoo, seconds2, ExpiryOption.NX, bbar1, bbar3)); - assertThat(jedis.hpttl("foo", "bar", "bare", "bared"), - contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), + contains(greaterThanOrEqualTo(seconds1 - 1), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAtAndExpireTime() { - long currSeconds = System.currentTimeMillis() / 1000; - long unixSeconds = currSeconds + 20; + public void hpexpireAndHpttl() { + long millis1 = 20_000; + long millis2 = 10_000; jedis.hset("foo", "bar", "car"); - jedis.hset("foo", "bare", "care"); - assertEquals(asList(1L, -2L), jedis.hexpireAt("foo", unixSeconds, "bar", "bared")); + assertEquals(asList(1L, -2L), jedis.hpexpire("foo", millis1, "bar", "bared")); jedis.hset("foo", "bared", "cared"); - assertEquals(asList(2L, 0L), jedis.hexpireAt("foo", currSeconds - 1, ExpiryOption.LT, "bar", "bared")); + assertEquals(asList(1L, 0L), jedis.hpexpire("foo", millis2, ExpiryOption.XX, "bar", "bared")); - assertThat(jedis.hexpireTime("foo", "bar", "bare", "bared"), - contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + assertThat(jedis.hpttl("foo", "bar", "bare", "bared"), + contains(both(lessThanOrEqualTo(millis2)).and(greaterThan(millis2 - 10)), equalTo(-2L), equalTo(-1L))); } @Test - public void hpexpireAtAndPexpireTime() { - long currMillis = System.currentTimeMillis(); - long unixMillis = currMillis + 20_000; + public void hpexpireAndHpttlBinary() { + long millis1 = 20_000; + long millis2 = 10_000; - jedis.hset("foo", "bar", "car"); - assertEquals(asList(1L, -2L), jedis.hpexpireAt("foo", unixMillis - 100, "bar", "bared")); + jedis.hset(bfoo, bbar1, bcar); + assertEquals(asList(1L, -2L), jedis.hpexpire(bfoo, millis1, bbar1, bbar3)); - jedis.hset("foo", "bared", "cared"); - assertEquals(asList(1L, 0L), jedis.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")); + jedis.hset(bfoo, bbar3, bcar); + assertEquals(asList(1L, 0L), jedis.hpexpire(bfoo, millis2, ExpiryOption.XX, bbar1, bbar3)); - assertThat(jedis.hpexpireTime("foo", "bar", "bare", "bared"), - contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); + assertThat(jedis.hpttl(bfoo, bbar1, bbar2, bbar3), + contains(both(lessThanOrEqualTo(millis2)).and(greaterThan(millis2 - 10)), equalTo(-2L), equalTo(-1L))); } @Test - public void hpersist() { - long seconds = 20; + public void hexpireAtAndExpireTime() { + long currSeconds = System.currentTimeMillis() / 1000; + long seconds1 = currSeconds + 20; + long seconds2 = currSeconds + 10; jedis.hset("foo", "bar", "car"); jedis.hset("foo", "bare", "care"); - assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + assertEquals(asList(1L, -2L), jedis.hexpireAt("foo", seconds1, "bar", "bared")); - assertEquals(asList(1L, -1L, -2L), jedis.hpersist("foo", "bar", "bare", "bared")); + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(1L, 1L), jedis.hexpireAt("foo", seconds2, ExpiryOption.LT, "bar", "bared")); - assertThat(jedis.httl("foo", "bar", "bare", "bared"), - contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + assertThat(jedis.hexpireTime("foo", "bar", "bare", "bared"), + contains(both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAndHttlBinary() { - long seconds = 20; + public void hexpireAtAndExpireTimeBinary() { + long currSeconds = System.currentTimeMillis() / 1000; + long seconds1 = currSeconds + 20; + long seconds2 = currSeconds + 10; jedis.hset(bfoo, bbar1, bcar); jedis.hset(bfoo, bbar2, bcar); - assertEquals(asList(1L, -2L), jedis.hexpire(bfoo, seconds, bbar1, bbar3)); - - jedis.hset(bfoo, bbar3, bcar); - assertEquals(asList(0L, 2L), jedis.hexpire(bfoo, -1, ExpiryOption.NX, bbar1, bbar3)); - - assertThat(jedis.httl(bfoo, bbar1, bbar2, bbar3), - contains(greaterThanOrEqualTo(seconds - 1L), equalTo(-1L), equalTo(-2L))); - } - - @Test - public void hpexpireAndHpttlBinary() { - long millis = 20_000; - - jedis.hset(bfoo, bbar1, bcar); - assertEquals(asList(1L, -2L), jedis.hpexpire(bfoo, millis, bbar1, bbar3)); + assertEquals(asList(1L, -2L), jedis.hexpireAt(bfoo, seconds1, bbar1, bbar3)); jedis.hset(bfoo, bbar3, bcar); - assertEquals(asList(2L, 0L), jedis.hpexpire(bfoo, -100, ExpiryOption.XX, bbar1, bbar3)); + assertEquals(asList(1L, 1L), jedis.hexpireAt(bfoo, seconds2, ExpiryOption.LT, bbar1, bbar3)); - assertThat(jedis.hpttl(bfoo, bbar1, bbar2, bbar3), - contains(equalTo(-2L), equalTo(-2L), equalTo(-1L))); + assertThat(jedis.hexpireTime(bfoo, bbar1, bbar2, bbar3), + contains(both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)), equalTo(-1L), + both(lessThanOrEqualTo(seconds2)).and(greaterThanOrEqualTo(seconds2 - 1)))); } @Test - public void hexpireAtAndExpireTimeBinary() { - long currSeconds = System.currentTimeMillis() / 1000; - long unixSeconds = currSeconds + 20; + public void hpexpireAtAndPexpireTime() { + long currMillis = System.currentTimeMillis(); + long unixMillis = currMillis + 20_000; - jedis.hset(bfoo, bbar1, bcar); - jedis.hset(bfoo, bbar2, bcar); - assertEquals(asList(1L, -2L), jedis.hexpireAt(bfoo, unixSeconds, bbar1, bbar3)); + jedis.hset("foo", "bar", "car"); + assertEquals(asList(1L, -2L), jedis.hpexpireAt("foo", unixMillis - 100, "bar", "bared")); - jedis.hset(bfoo, bbar3, bcar); - assertEquals(asList(2L, 0L), jedis.hexpireAt(bfoo, currSeconds - 1, ExpiryOption.LT, bbar1, bbar3)); + jedis.hset("foo", "bared", "cared"); + assertEquals(asList(1L, 0L), jedis.hpexpireAt("foo", unixMillis, ExpiryOption.GT, "bar", "bared")); - assertThat(jedis.hexpireTime(bfoo, bbar1, bbar2, bbar3), - contains(equalTo(-2L), equalTo(-1L), equalTo(-1L))); + assertThat(jedis.hpexpireTime("foo", "bar", "bare", "bared"), + contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); } @Test @@ -755,6 +754,20 @@ public void hpexpireAtAndPexpireTimeBinary() { contains(equalTo(unixMillis), equalTo(-2L), equalTo(-1L))); } + @Test + public void hpersist() { + long seconds = 20; + + jedis.hset("foo", "bar", "car"); + jedis.hset("foo", "bare", "care"); + assertEquals(asList(1L, -2L), jedis.hexpire("foo", seconds, "bar", "bared")); + + assertEquals(asList(1L, -1L, -2L), jedis.hpersist("foo", "bar", "bare", "bared")); + + assertThat(jedis.httl("foo", "bar", "bare", "bared"), + contains(equalTo(-1L), equalTo(-1L), equalTo(-2L))); + } + @Test public void hpersistBinary() { long seconds = 20;