Unverified Commit acf3495e authored by Viktor Söderqvist's avatar Viktor Söderqvist Committed by GitHub
Browse files

Sort out the mess around writable replicas and lookupKeyRead/Write (#9572)

Writable replicas now no longer use the values of expired keys. Expired keys are
deleted when lookupKeyWrite() is used, even on a writable replica. Previously,
writable replicas could use the value of an expired key in write commands such
as INCR, SUNIONSTORE, etc..

This commit also sorts out the mess around the functions lookupKeyRead() and
lookupKeyWrite() so they now indicate what we intend to do with the key and
are not affected by the command calling them.

Multi-key commands like SUNIONSTORE, ZUNIONSTORE, COPY and SORT with the
store option now use lookupKeyRead() for the keys they're reading from (which will
not allow reading from logically expired keys).

This commit also fixes a bug where PFCOUNT could return a value of an
expired key.

Test modules commands have their readonly and write flags updated to correctly
reflect their lookups for reading or writing. Modules are not required to
correctly reflect this in their command flags, but this change is made for
consistency since the tests serve as usage examples.

Fixes #6842. Fixes #7475.
parent 4d870078
......@@ -238,19 +238,19 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if (RedisModule_Init(ctx, "stream", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "stream.add", stream_add, "",
if (RedisModule_CreateCommand(ctx, "stream.add", stream_add, "write",
1, 1, 1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "stream.addn", stream_addn, "",
if (RedisModule_CreateCommand(ctx, "stream.addn", stream_addn, "write",
1, 1, 1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "stream.delete", stream_delete, "",
if (RedisModule_CreateCommand(ctx, "stream.delete", stream_delete, "write",
1, 1, 1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "stream.range", stream_range, "",
if (RedisModule_CreateCommand(ctx, "stream.range", stream_range, "write",
1, 1, 1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx, "stream.trim", stream_trim, "",
if (RedisModule_CreateCommand(ctx, "stream.trim", stream_trim, "write",
1, 1, 1) == REDISMODULE_ERR)
return REDISMODULE_ERR;
......
......@@ -98,7 +98,7 @@ int LazyFreeLinkLen_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
if (argc != 2) return RedisModule_WrongArity(ctx);
RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1],
REDISMODULE_READ|REDISMODULE_WRITE);
REDISMODULE_READ);
int type = RedisModule_KeyType(key);
if (type != REDISMODULE_KEYTYPE_EMPTY &&
RedisModule_ModuleTypeGetType(key) != LazyFreeLinkType)
......
......@@ -262,7 +262,7 @@ int testrdb_get_key(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_OK;
}
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
RedisModuleString *str = RedisModule_ModuleTypeGetValue(key);
RedisModule_CloseKey(key);
RedisModule_ReplyWithString(ctx, str);
......
......@@ -22,7 +22,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
REDISMODULE_NOT_USED(argc);
if (RedisModule_Init(ctx, "zset", 1, REDISMODULE_APIVER_1) ==
REDISMODULE_OK &&
RedisModule_CreateCommand(ctx, "zset.rem", zset_rem, "",
RedisModule_CreateCommand(ctx, "zset.rem", zset_rem, "write",
1, 1, 1) == REDISMODULE_OK)
return REDISMODULE_OK;
else
......
......@@ -1032,6 +1032,44 @@ foreach {pop} {BLPOP BLMPOP_LEFT} {
set _ $res
} {}
test {SWAPDB awakes blocked client} {
r flushall
r select 1
r rpush k hello
r select 9
set rd [redis_deferring_client]
$rd brpop k 5
wait_for_blocked_clients_count 1
r swapdb 1 9
$rd read
} {k hello} {singledb:skip}
test {SWAPDB awakes blocked client, but the key already expired} {
r flushall
r debug set-active-expire 0
r select 1
r rpush k hello
r pexpire k 100
set rd [redis_deferring_client]
$rd select 9
assert_equal {OK} [$rd read]
$rd client id
set id [$rd read]
$rd brpop k 1
wait_for_blocked_clients_count 1
after 101
r swapdb 1 9
# The SWAPDB command tries to awake the blocked client, but it remains
# blocked because the key is expired. Check that the deferred client is
# still blocked. Then unblock it.
assert_match "*flags=b*" [r client list id $id]
r client unblock $id
assert_equal {} [$rd read]
# Restore server and client state
r debug set-active-expire 1
r select 9
} {OK} {singledb:skip}
foreach {pop} {BLPOP BLMPOP_LEFT} {
test "$pop when new key is moved into place" {
set rd [redis_deferring_client]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment