Skip to content

Commit 2904c35

Browse files
committed
Add MGETPXT with the same semantics
Remove the "overload" as non-precision timestamp isn't useful in the intended context Signed-off-by: Arcadiy Ivanov <[email protected]>
1 parent 7ccf367 commit 2904c35

5 files changed

Lines changed: 169 additions & 7 deletions

File tree

src/commands.def

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10558,6 +10558,32 @@ struct COMMAND_ARG MGET_Args[] = {
1055810558
{MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)},
1055910559
};
1056010560

10561+
/********** MGETPXT ********************/
10562+
10563+
#ifndef SKIP_CMD_HISTORY_TABLE
10564+
/* MGETPXT history */
10565+
#define MGETPXT_History NULL
10566+
#endif
10567+
10568+
#ifndef SKIP_CMD_TIPS_TABLE
10569+
/* MGETPXT tips */
10570+
const char *MGETPXT_Tips[] = {
10571+
"request_policy:multi_shard",
10572+
};
10573+
#endif
10574+
10575+
#ifndef SKIP_CMD_KEY_SPECS_TABLE
10576+
/* MGETPXT key specs */
10577+
keySpec MGETPXT_Keyspecs[1] = {
10578+
{NULL,CMD_KEY_RO|CMD_KEY_ACCESS,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={-1,1,0}}
10579+
};
10580+
#endif
10581+
10582+
/* MGETPXT argument table */
10583+
struct COMMAND_ARG MGETPXT_Args[] = {
10584+
{MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_MULTIPLE,0,NULL)},
10585+
};
10586+
1056110587
/********** MSET ********************/
1056210588

1056310589
#ifndef SKIP_CMD_HISTORY_TABLE
@@ -11163,6 +11189,7 @@ struct COMMAND_STRUCT serverCommandTable[] = {
1116311189
{MAKE_CMD("incrbyfloat","Increment the floating point value of a key by a number. Uses 0 as initial value if the key doesn't exist.","O(1)","2.6.0",CMD_DOC_NONE,NULL,NULL,"string",COMMAND_GROUP_STRING,INCRBYFLOAT_History,0,INCRBYFLOAT_Tips,0,incrbyfloatCommand,3,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_STRING,INCRBYFLOAT_Keyspecs,1,NULL,2),.args=INCRBYFLOAT_Args},
1116411190
{MAKE_CMD("lcs","Finds the longest common substring.","O(N*M) where N and M are the lengths of s1 and s2, respectively","7.0.0",CMD_DOC_NONE,NULL,NULL,"string",COMMAND_GROUP_STRING,LCS_History,0,LCS_Tips,0,lcsCommand,-3,CMD_READONLY,ACL_CATEGORY_STRING,LCS_Keyspecs,1,NULL,6),.args=LCS_Args},
1116511191
{MAKE_CMD("mget","Atomically returns the string values of one or more keys.","O(N) where N is the number of keys to retrieve.","1.0.0",CMD_DOC_NONE,NULL,NULL,"string",COMMAND_GROUP_STRING,MGET_History,0,MGET_Tips,1,mgetCommand,-2,CMD_READONLY|CMD_FAST,ACL_CATEGORY_STRING,MGET_Keyspecs,1,NULL,1),.args=MGET_Args},
11192+
{MAKE_CMD("mgetpxt","Atomically returns the string values of one or more keys and their millisecond expiration, if available.","O(N) where N is the number of keys to retrieve.","1.0.0",CMD_DOC_NONE,NULL,NULL,"string",COMMAND_GROUP_STRING,MGETPXT_History,0,MGETPXT_Tips,1,mgetpxtCommand,-2,CMD_READONLY|CMD_FAST,ACL_CATEGORY_STRING|ACL_CATEGORY_KEYSPACE,MGETPXT_Keyspecs,1,NULL,1),.args=MGETPXT_Args},
1116611193
{MAKE_CMD("mset","Atomically creates or modifies the string values of one or more keys.","O(N) where N is the number of keys to set.","1.0.1",CMD_DOC_NONE,NULL,NULL,"string",COMMAND_GROUP_STRING,MSET_History,0,MSET_Tips,2,msetCommand,-3,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_STRING,MSET_Keyspecs,1,NULL,1),.args=MSET_Args},
1116711194
{MAKE_CMD("msetnx","Atomically modifies the string values of one or more keys only when all keys don't exist.","O(N) where N is the number of keys to set.","1.0.1",CMD_DOC_NONE,NULL,NULL,"string",COMMAND_GROUP_STRING,MSETNX_History,0,MSETNX_Tips,0,msetnxCommand,-3,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_STRING,MSETNX_Keyspecs,1,NULL,1),.args=MSETNX_Args},
1116811195
{MAKE_CMD("psetex","Sets both string value and expiration time in milliseconds of a key. The key is created if it doesn't exist.","O(1)","2.6.0",CMD_DOC_DEPRECATED,"`SET` with the `PX` argument","2.6.12","string",COMMAND_GROUP_STRING,PSETEX_History,0,PSETEX_Tips,0,psetexCommand,4,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_STRING,PSETEX_Keyspecs,1,NULL,3),.args=PSETEX_Args},

src/commands/mgetpxt.json

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"MGETPXT": {
3+
"summary": "Atomically returns the string values of one or more keys and their millisecond expiration, if available.",
4+
"complexity": "O(N) where N is the number of keys to retrieve.",
5+
"group": "string",
6+
"since": "1.0.0",
7+
"arity": -2,
8+
"function": "mgetpxtCommand",
9+
"command_flags": [
10+
"READONLY",
11+
"FAST"
12+
],
13+
"acl_categories": [
14+
"STRING",
15+
"KEYSPACE"
16+
],
17+
"command_tips": [
18+
"REQUEST_POLICY:MULTI_SHARD"
19+
],
20+
"key_specs": [
21+
{
22+
"flags": [
23+
"RO",
24+
"ACCESS"
25+
],
26+
"begin_search": {
27+
"index": {
28+
"pos": 1
29+
}
30+
},
31+
"find_keys": {
32+
"range": {
33+
"lastkey": -1,
34+
"step": 1,
35+
"limit": 0
36+
}
37+
}
38+
}
39+
],
40+
"reply_schema": {
41+
"description": "List of values at the specified keys.",
42+
"type": "array",
43+
"minItems": 1,
44+
"items": {
45+
"oneOf": [
46+
{
47+
"type": "array",
48+
"items": {
49+
"type": "array",
50+
"minItems": 2,
51+
"maxItems": 2,
52+
"items": [
53+
{
54+
"description": "The value of the key.",
55+
"type": "string"
56+
},
57+
{
58+
"oneOf": [
59+
{
60+
"type": "integer",
61+
"description": "Expiration Unix timestamp in milliseconds.",
62+
"minimum": 0
63+
},
64+
{
65+
"const": -1,
66+
"description": "The key exists but has no associated expiration time."
67+
}
68+
]
69+
}
70+
]
71+
}
72+
},
73+
{
74+
"type": "null"
75+
}
76+
]
77+
}
78+
},
79+
"arguments": [
80+
{
81+
"name": "key",
82+
"type": "key",
83+
"key_spec_index": 0,
84+
"multiple": true
85+
}
86+
]
87+
}
88+
}

src/server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3856,6 +3856,7 @@ void rpoplpushCommand(client *c);
38563856
void lmoveCommand(client *c);
38573857
void infoCommand(client *c);
38583858
void mgetCommand(client *c);
3859+
void mgetpxtCommand(client *c);
38593860
void monitorCommand(client *c);
38603861
void expireCommand(client *c);
38613862
void expireatCommand(client *c);

src/t_string.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ void getCommand(client *c) {
393393
getGenericCommand(c);
394394
}
395395

396-
void getExpireGenericCommand(client *c, int output_ms) {
396+
void getpxtCommand(client *c) {
397397
long long expire;
398398
robj *o;
399399

@@ -413,14 +413,10 @@ void getExpireGenericCommand(client *c, int output_ms) {
413413
if (expire == -1) {
414414
addReplyLongLong(c, -1);
415415
} else {
416-
addReplyLongLong(c, output_ms ? expire : ((expire + 500) / 1000));
416+
addReplyLongLong(c, expire);
417417
}
418418
}
419419

420-
void getpxtCommand(client *c) {
421-
getExpireGenericCommand(c, 1);
422-
}
423-
424420
/*
425421
* GETEX <key> [PERSIST][EX seconds][PX milliseconds][EXAT seconds-timestamp][PXAT milliseconds-timestamp]
426422
*
@@ -636,6 +632,34 @@ void mgetCommand(client *c) {
636632
}
637633
}
638634

635+
void mgetpxtCommand(client *c) {
636+
int j;
637+
638+
addReplyArrayLen(c, c->argc - 1);
639+
for (j = 1; j < c->argc; j++) {
640+
robj *o = lookupKeyRead(c->db, c->argv[j]);
641+
if (o == NULL) {
642+
addReplyNull(c);
643+
} else {
644+
if (o->type != OBJ_STRING) {
645+
addReplyNull(c);
646+
} else {
647+
addReplyArrayLen(c, 2);
648+
addReplyBulk(c, o);
649+
650+
/* The key exists. Return -1 if it has no expire, or the actual
651+
* expire value otherwise. */
652+
long long expire = getExpire(c->db, c->argv[j]);
653+
if (expire == -1) {
654+
addReplyLongLong(c, -1);
655+
} else {
656+
addReplyLongLong(c, expire);
657+
}
658+
}
659+
}
660+
}
661+
}
662+
639663
void msetGenericCommand(client *c, int nx) {
640664
int j;
641665

tests/unit/type/string.tcl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,28 @@ start_server {tags {"string"}} {
214214
r mget foo{t} baazz{t} bar{t} myset{t}
215215
} {BAR {} FOO {}}
216216

217+
test {MGETPXT} {
218+
r flushdb
219+
r set foo{t} BAR pxat 17344823940230
220+
r set bar{t} FOO pxat 17344823940231
221+
r mgetpxt foo{t} bar{t}
222+
} {{BAR 17344823940230} {FOO 17344823940231}}
223+
224+
test {MGETPXT against non existing key} {
225+
r mgetpxt foo{t} baazz{t} bar{t}
226+
} {{BAR 17344823940230} {} {FOO 17344823940231}}
227+
228+
test {MGETPXT against non-string key} {
229+
r sadd myset{t} ciao
230+
r sadd myset{t} bau
231+
r mgetpxt foo{t} baazz{t} bar{t} myset{t}
232+
} {{BAR 17344823940230} {} {FOO 17344823940231} {}}
233+
234+
test {MGETPXT against a key with no expiration} {
235+
r set baz{t} BAZ
236+
r mgetpxt foo{t} baz{t} bar{t}
237+
} {{BAR 17344823940230} {BAZ -1} {FOO 17344823940231}}
238+
217239
test {GETSET (set new value)} {
218240
r del foo
219241
list [r getset foo xyz] [r get foo]
@@ -664,7 +686,7 @@ if {[string match {*jemalloc*} [s mem_allocator]]} {
664686
r getpxt foo
665687
} {bar 17344823940230}
666688

667-
test "GETPXT after SET" {
689+
test "GETPXT after SET with no expiration" {
668690
r del foo
669691
r set foo bar
670692
r getpxt foo

0 commit comments

Comments
 (0)