Skip to content

Commit 0582c3b

Browse files
authored
Add msetex command (#4361)
* Add msetex command * Refactor to return boolean * Change EnabledOnCOmmand with SinceRedisVersion * Add cluster test - crosslot not supported * Revert "Change EnabledOnCOmmand with SinceRedisVersion" This reverts commit 9699a80. * Register extensions for UnifiedJedis base tests * Fix javadoc * Format tests * Add tests to formatter includes * Remove javadoc * Revert "Remove javadoc" This reverts commit 3f3a81f. * Address comments * Add dedicated MSetExParams object for the MSETEX command * Add msetex params to formatter
1 parent d5e98ab commit 0582c3b

21 files changed

+595
-74
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,12 @@
518518
<include>src/test/java/redis/clients/jedis/commands/jedis/ClusterStreamsCommandsTest.java</include>
519519
<include>src/test/java/redis/clients/jedis/commands/jedis/PooledStreamsCommandsTest.java</include>
520520
<include>src/test/java/redis/clients/jedis/resps/StreamEntryDeletionResultTest.java</include>
521+
<include>src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsStringCommandsTest.java</include>
522+
<include>src/test/java/redis/clients/jedis/commands/jedis/BinaryValuesCommandsTest.java</include>
523+
<include>src/test/java/redis/clients/jedis/commands/jedis/StringValuesCommandsTest.java</include>
524+
<include>src/test/java/redis/clients/jedis/commands/unified/BinaryValuesCommandsTestBase.java</include>
525+
<include>src/test/java/redis/clients/jedis/commands/unified/StringValuesCommandsTestBase.java</include>
526+
<include>src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterStringValuesCommandsTest.java</include>
521527
<include>**/VectorSet*.java</include>
522528
<include>**/VectorTestUtils.java</include>
523529
<include>**/VAddParams.java</include>
@@ -538,6 +544,7 @@
538544
<include>**/ClientTestUtil.java</include>
539545
<include>**/ReflectionTestUtil.java</include>
540546
<include>**/*CommandFlags*.java</include>
547+
<include>**/*MSetExParams*.java</include>
541548
</includes>
542549
</configuration>
543550
<executions>

src/main/java/redis/clients/jedis/CommandObjects.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ protected RedisProtocol getProtocol() {
4949

5050
protected volatile CommandKeyArgumentPreProcessor keyPreProcessor = null;
5151
private JedisBroadcastAndRoundRobinConfig broadcastAndRoundRobinConfig = null;
52-
private Lock mapperLock = new ReentrantLock(true);
52+
private Lock mapperLock = new ReentrantLock(true);
5353
private volatile JsonObjectMapper jsonObjectMapper;
5454
private final AtomicInteger searchDialect = new AtomicInteger(SearchProtocol.DEFAULT_DIALECT);
5555

@@ -588,6 +588,20 @@ public final CommandObject<Long> msetnx(String... keysvalues) {
588588
return new CommandObject<>(addFlatKeyValueArgs(commandArguments(MSETNX), keysvalues), BuilderFactory.LONG);
589589
}
590590

591+
public final CommandObject<Boolean> msetex(MSetExParams params, String... keysvalues) {
592+
CommandArguments args = commandArguments(Command.MSETEX).add(keysvalues.length / 2);
593+
addFlatKeyValueArgs(args, keysvalues);
594+
args.addParams(params);
595+
return new CommandObject<>(args, BuilderFactory.BOOLEAN);
596+
}
597+
598+
public final CommandObject<Boolean> msetex(MSetExParams params, byte[]... keysvalues) {
599+
CommandArguments args = commandArguments(Command.MSETEX).add(keysvalues.length / 2);
600+
addFlatKeyValueArgs(args, keysvalues);
601+
args.addParams(params);
602+
return new CommandObject<>(args, BuilderFactory.BOOLEAN);
603+
}
604+
591605
public final CommandObject<String> mset(byte[]... keysvalues) {
592606
return new CommandObject<>(addFlatKeyValueArgs(commandArguments(MSET), keysvalues), BuilderFactory.STRING);
593607
}
@@ -2977,7 +2991,7 @@ public final CommandObject<List<Object>> xreadGroup(byte[] groupName, byte[] con
29772991
}
29782992

29792993
public final CommandObject<List<Map.Entry<byte[], List<StreamEntryBinary>>>> xreadGroupBinary(
2980-
byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams,
2994+
byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams,
29812995
Map.Entry<byte[], StreamEntryID>... streams) {
29822996
CommandArguments args = commandArguments(XREADGROUP)
29832997
.add(GROUP).add(groupName).add(consumer)
@@ -2992,7 +3006,7 @@ public final CommandObject<List<Map.Entry<byte[], List<StreamEntryBinary>>>> xre
29923006
}
29933007

29943008
public final CommandObject<Map<byte[], List<StreamEntryBinary>>> xreadGroupBinaryAsMap(
2995-
byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams,
3009+
byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams,
29963010
Map.Entry<byte[], StreamEntryID>... streams) {
29973011
CommandArguments args = commandArguments(XREADGROUP)
29983012
.add(GROUP).add(groupName).add(consumer)

src/main/java/redis/clients/jedis/Jedis.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,12 @@ public long msetnx(final byte[]... keysvalues) {
984984
return connection.executeCommand(commandObjects.msetnx(keysvalues));
985985
}
986986

987+
@Override
988+
public boolean msetex(final MSetExParams params, final byte[]... keysvalues) {
989+
checkIsInMultiOrPipeline();
990+
return connection.executeCommand(commandObjects.msetex(params, keysvalues));
991+
}
992+
987993
/**
988994
* DECRBY work just like {@link Jedis#decr(byte[]) DECR} but instead to decrement by 1 the
989995
* decrement is integer.
@@ -5597,6 +5603,12 @@ public long msetnx(final String... keysvalues) {
55975603
return connection.executeCommand(commandObjects.msetnx(keysvalues));
55985604
}
55995605

5606+
@Override
5607+
public boolean msetex(final MSetExParams params, final String... keysvalues) {
5608+
checkIsInMultiOrPipeline();
5609+
return connection.executeCommand(commandObjects.msetex(params, keysvalues));
5610+
}
5611+
56005612
/**
56015613
* IDECRBY work just like {@link Jedis#decr(String) INCR} but instead to decrement by 1 the
56025614
* decrement is integer.
@@ -5805,13 +5817,13 @@ public String hget(final String key, final String field) {
58055817
}
58065818

58075819
@Override
5808-
public List<String> hgetex(String key, HGetExParams params, String... fields) {
5820+
public List<String> hgetex(String key, HGetExParams params, String... fields) {
58095821
checkIsInMultiOrPipeline();
58105822
return connection.executeCommand(commandObjects.hgetex(key, params, fields));
58115823
}
58125824

58135825
@Override
5814-
public List<String> hgetdel(String key, String... fields) {
5826+
public List<String> hgetdel(String key, String... fields) {
58155827
checkIsInMultiOrPipeline();
58165828
return connection.executeCommand(commandObjects.hgetdel(key, fields));
58175829
}

src/main/java/redis/clients/jedis/PipeliningBase.java

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ public Response<Long> msetnx(String... keysvalues) {
349349
return appendCommand(commandObjects.msetnx(keysvalues));
350350
}
351351

352+
@Override
353+
public Response<Boolean> msetex(MSetExParams params, String... keysvalues) {
354+
return appendCommand(commandObjects.msetex(params, keysvalues));
355+
}
356+
352357
@Override
353358
public Response<Long> incr(String key) {
354359
return appendCommand(commandObjects.incr(key));
@@ -630,13 +635,13 @@ public Response<Long> hset(String key, Map<String, String> hash) {
630635
* and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters.
631636
* This command can overwrite any existing fields in the hash.
632637
* If key does not exist, a new key holding a hash is created.
633-
*
638+
*
634639
* @param key the key of the hash
635640
* @param params additional parameters for the HSETEX command
636641
* @param field the field in the hash to set
637642
* @param value the value to set in the specified field
638-
* @return 0 if no fields were set, 1 if all the fields were set
639-
*
643+
* @return 0 if no fields were set, 1 if all the fields were set
644+
*
640645
* @see HSetExParams
641646
*/
642647
@Override
@@ -649,12 +654,12 @@ public Response<Long> hsetex(String key, HSetExParams params, String field, Stri
649654
* and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters.
650655
* This command can overwrite any existing fields in the hash.
651656
* If key does not exist, a new key holding a hash is created.
652-
*
657+
*
653658
* @param key the key of the hash
654659
* @param params the parameters for the HSetEx command
655660
* @param hash the map containing field-value pairs to set in the hash
656-
* @return 0 if no fields were set, 1 if all the fields were set
657-
*
661+
* @return 0 if no fields were set, 1 if all the fields were set
662+
*
658663
* @see HSetExParams
659664
*/
660665
@Override
@@ -668,14 +673,14 @@ public Response<String> hget(String key, String field) {
668673
}
669674

670675
/**
671-
* Retrieves the values associated with the specified fields in a hash stored at the given key
676+
* Retrieves the values associated with the specified fields in a hash stored at the given key
672677
* and optionally sets their expiration. Use `HGetExParams` object to specify expiration parameters.
673678
*
674679
* @param key the key of the hash
675680
* @param params additional parameters for the HGETEX command
676681
* @param fields the fields whose values are to be retrieved
677682
* @return a list of the value associated with each field or nil if the field doesn’t exist.
678-
*
683+
*
679684
* @see HGetExParams
680685
*/
681686
@Override
@@ -2062,13 +2067,13 @@ public Response<Long> hset(byte[] key, Map<byte[], byte[]> hash) {
20622067
* and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters.
20632068
* This command can overwrite any existing fields in the hash.
20642069
* If key does not exist, a new key holding a hash is created.
2065-
*
2070+
*
20662071
* @param key the key of the hash
20672072
* @param params the parameters for the HSetEx command
20682073
* @param field the field in the hash to set
20692074
* @param value the value to set in the specified field
2070-
* @return 0 if no fields were set, 1 if all the fields were set
2071-
*
2075+
* @return 0 if no fields were set, 1 if all the fields were set
2076+
*
20722077
* @see HSetExParams
20732078
*/
20742079
@Override
@@ -2081,12 +2086,12 @@ public Response<Long> hsetex(byte[] key, HSetExParams params, byte[] field, byte
20812086
* and optionally set their expiration. Use `HSetExParams` object to specify expiration parameters.
20822087
* This command can overwrite any existing fields in the hash.
20832088
* If key does not exist, a new key holding a hash is created.
2084-
*
2089+
*
20852090
* @param key the key of the hash
20862091
* @param params the parameters for the HSetEx command
20872092
* @param hash the map containing field-value pairs to set in the hash
2088-
* @return 0 if no fields were set, 1 if all the fields were set
2089-
*
2093+
* @return 0 if no fields were set, 1 if all the fields were set
2094+
*
20902095
* @see HSetExParams
20912096
*/
20922097
@Override
@@ -2098,16 +2103,16 @@ public Response<Long> hsetex(byte[] key, HSetExParams params, Map<byte[], byte[]
20982103
public Response<byte[]> hget(byte[] key, byte[] field) {
20992104
return appendCommand(commandObjects.hget(key, field));
21002105
}
2101-
2106+
21022107
/**
2103-
* Retrieves the values associated with the specified fields in a hash stored at the given key
2108+
* Retrieves the values associated with the specified fields in a hash stored at the given key
21042109
* and optionally sets their expiration. Use `HGetExParams` object to specify expiration parameters.
21052110
*
21062111
* @param key the key of the hash
21072112
* @param params additional parameters for the HGETEX command
21082113
* @param fields the fields whose values are to be retrieved
21092114
* @return a list of the value associated with each field or nil if the field doesn’t exist.
2110-
*
2115+
*
21112116
* @see HGetExParams
21122117
*/
21132118
@Override
@@ -3538,6 +3543,11 @@ public Response<String> mset(byte[]... keysvalues) {
35383543
return appendCommand(commandObjects.mset(keysvalues));
35393544
}
35403545

3546+
@Override
3547+
public Response<Boolean> msetex(MSetExParams params, byte[]... keysvalues) {
3548+
return appendCommand(commandObjects.msetex(params, keysvalues));
3549+
}
3550+
35413551
@Override
35423552
public Response<Long> msetnx(byte[]... keysvalues) {
35433553
return appendCommand(commandObjects.msetnx(keysvalues));

src/main/java/redis/clients/jedis/Protocol.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ public static enum Command implements ProtocolCommand {
287287
KEYS, RANDOMKEY, RENAME, RENAMENX, DUMP, RESTORE, DBSIZE, SELECT, SWAPDB, MIGRATE, ECHO, //
288288
EXPIRE, EXPIREAT, EXPIRETIME, PEXPIRE, PEXPIREAT, PEXPIRETIME, TTL, PTTL, // <-- key expiration
289289
MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, SORT_RO, INFO, SHUTDOWN, MONITOR, CONFIG, LCS, //
290-
GETSET, MGET, SETNX, SETEX, PSETEX, MSET, MSETNX, DECR, DECRBY, INCR, INCRBY, INCRBYFLOAT,
290+
GETSET, MGET, SETNX, SETEX, PSETEX, MSETEX, MSET, MSETNX, DECR, DECRBY, INCR, INCRBY, INCRBYFLOAT,
291291
STRLEN, APPEND, SUBSTR, // <-- string
292292
SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, BITCOUNT, BITOP, BITFIELD, BITFIELD_RO, // <-- bit (string)
293293
HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, HSTRLEN,

src/main/java/redis/clients/jedis/StaticCommandFlagsRegistryInitializer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ static void initialize(StaticCommandFlagsRegistry.Builder builder) {
299299
builder.register("LSET", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));
300300
builder.register("MSET", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));
301301
builder.register("MSETNX", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));
302+
builder.register("MSETEX", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));
302303
builder.register("PFMERGE", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));
303304
builder.register("PSETEX", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));
304305
builder.register("RESTORE", EnumSet.of(CommandFlag.DENYOOM, CommandFlag.WRITE));

src/main/java/redis/clients/jedis/UnifiedJedis.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,11 @@ public long msetnx(String... keysvalues) {
968968
return executeCommand(commandObjects.msetnx(keysvalues));
969969
}
970970

971+
@Override
972+
public boolean msetex(MSetExParams params, String... keysvalues) {
973+
return executeCommand(commandObjects.msetex(params, keysvalues));
974+
}
975+
971976
@Override
972977
public List<byte[]> mget(byte[]... keys) {
973978
return executeCommand(commandObjects.mget(keys));
@@ -978,6 +983,11 @@ public String mset(byte[]... keysvalues) {
978983
return executeCommand(commandObjects.mset(keysvalues));
979984
}
980985

986+
@Override
987+
public boolean msetex(MSetExParams params, byte[]... keysvalues) {
988+
return executeCommand(commandObjects.msetex(params, keysvalues));
989+
}
990+
981991
@Override
982992
public long msetnx(byte[]... keysvalues) {
983993
return executeCommand(commandObjects.msetnx(keysvalues));
@@ -1446,12 +1456,12 @@ public long hsetex(String key, HSetExParams params, String field, String value)
14461456
public long hsetex(String key, HSetExParams params, Map<String, String> hash) {
14471457
return executeCommand(commandObjects.hsetex(key, params, hash));
14481458
}
1449-
1459+
14501460
@Override
14511461
public String hget(String key, String field) {
14521462
return executeCommand(commandObjects.hget(key, field));
14531463
}
1454-
1464+
14551465
@Override
14561466
public List<String> hgetex(String key, HGetExParams params, String... fields) {
14571467
return executeCommand(commandObjects.hgetex(key, params, fields));
@@ -3997,7 +4007,7 @@ public SearchResult ftSearch(String indexName, String query, FTSearchParams para
39974007

39984008
/**
39994009
* {@link FTSearchParams#limit(int, int)} will be ignored.
4000-
*
4010+
*
40014011
* @param batchSize batch size
40024012
* @param indexName index name
40034013
* @param query query

src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import redis.clients.jedis.params.GetExParams;
66
import redis.clients.jedis.params.SetParams;
7+
import redis.clients.jedis.params.MSetExParams;
8+
79
import redis.clients.jedis.params.LCSParams;
810
import redis.clients.jedis.resps.LCSMatchResult;
911

@@ -45,6 +47,28 @@ public interface StringBinaryCommands extends BitBinaryCommands {
4547

4648
long msetnx(byte[]... keysvalues);
4749

50+
/**
51+
* Multi-set with optional condition and expiration.
52+
* <p>
53+
* Sets the respective keys to the respective values, similar to {@link #mset(byte[]...) MSET},
54+
* but allows conditional set (NX|XX) and expiration options via {@link MSetExParams}.
55+
* If the condition is not met for any key, no key is set.
56+
* <p>
57+
* Both MSET and MSETEX are atomic operations. This means that if multiple keys are provided,
58+
* another client will either see the changes for all keys at once, or no changes at all.
59+
* <p>
60+
* Options (in {@link MSetExParams}): NX or XX, and expiration: EX seconds | PX milliseconds |
61+
* EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL.
62+
* <p>
63+
* Time complexity: O(N) where N is the number of keys to set.
64+
* @param params condition and expiration parameters
65+
* @param keysvalues pairs of keys and their values, e.g. {@code msetex(params, "foo".getBytes(), "foovalue".getBytes(), "bar".getBytes(), "barvalue".getBytes())}
66+
* @return {@code true} if all the keys were set, {@code false} if none were set (condition not satisfied)
67+
* @see #mset(byte[]...)
68+
* @see #msetnx(byte[]...)
69+
*/
70+
boolean msetex(MSetExParams params, byte[]... keysvalues);
71+
4872
long incr(byte[] key);
4973

5074
long incrBy(byte[] key, long increment);

src/main/java/redis/clients/jedis/commands/StringCommands.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import redis.clients.jedis.params.GetExParams;
66
import redis.clients.jedis.params.SetParams;
7+
import redis.clients.jedis.params.MSetExParams;
8+
79
import redis.clients.jedis.params.LCSParams;
810
import redis.clients.jedis.resps.LCSMatchResult;
911

@@ -210,6 +212,28 @@ public interface StringCommands extends BitCommands {
210212
*/
211213
long msetnx(String... keysvalues);
212214

215+
/**
216+
* Multi-set with optional condition and expiration.
217+
* <p>
218+
* Sets the respective keys to the respective values, similar to {@link #mset(String...) MSET},
219+
* but allows conditional set (NX|XX) and expiration options via {@link MSetExParams}.
220+
* If the condition is not met for any key, no key is set.
221+
* <p>
222+
* Both MSET and MSETEX are atomic operations. This means that if multiple keys are provided,
223+
* another client will either see the changes for all keys at once, or no changes at all.
224+
* <p>
225+
* Options (in {@link MSetExParams}): NX or XX, and expiration: EX seconds | PX milliseconds |
226+
* EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL.
227+
* <p>
228+
* Time complexity: O(N) where N is the number of keys to set.
229+
* @param params condition and expiration parameters
230+
* @param keysvalues pairs of keys and their values, e.g. {@code msetex(params, "foo", "foovalue", "bar", "barvalue")}
231+
* @return {@code true} if all the keys were set, {@code false} if none were set (condition not satisfied)
232+
* @see #mset(String...)
233+
* @see #msetnx(String...)
234+
*/
235+
boolean msetex(MSetExParams params, String... keysvalues);
236+
213237
/**
214238
* <b><a href="http://redis.io/commands/incr">Incr Command</a></b>
215239
* Increment the number stored at key by one. If the key does not exist or contains a value of a

0 commit comments

Comments
 (0)