futriix/tests/unit/moduleapi/async_rm_call.tcl
Binbin 70624ea63d
Change all the lazyfree configurations to yes by default (#913)
## Set replica-lazy-flush and lazyfree-lazy-user-flush to yes by
default.
There are many problems with running flush synchronously. Even in
single CPU environments, the thread managers should balance between
the freeing and serving incoming requests.

## Set lazy eviction, expire, server-del, user-del to yes by default
We now have a del and a lazyfree del, we also have these configuration
items to control: lazyfree-lazy-eviction, lazyfree-lazy-expire,
lazyfree-lazy-server-del, lazyfree-lazy-user-del. In most cases lazyfree
is better since it reduces the risk of blocking the main thread, and
because we have lazyfreeGetFreeEffort, on those with high effor
(currently
64) will use lazyfree.

Part of #653.

---------

Signed-off-by: Binbin <binloveplay1314@qq.com>
2024-09-02 07:07:17 -07:00

438 lines
14 KiB
Tcl

set testmodule [file normalize tests/modules/blockedclient.so]
set testmodule2 [file normalize tests/modules/postnotifications.so]
set testmodule3 [file normalize tests/modules/blockonkeys.so]
start_server {tags {"modules"}} {
r module load $testmodule
test {Locked GIL acquisition from async RM_Call} {
assert_equal {OK} [r do_rm_call_async acquire_gil]
}
test "Blpop on async RM_Call fire and forget" {
assert_equal {Blocked} [r do_rm_call_fire_and_forget blpop l 0]
r lpush l a
assert_equal {0} [r llen l]
}
test "Blpop on threaded async RM_Call" {
set rd [valkey_deferring_client]
$rd do_rm_call_async_on_thread blpop l 0
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {l a}
wait_for_blocked_clients_count 0
$rd close
}
foreach cmd {do_rm_call_async do_rm_call_async_script_mode } {
test "Blpop on async RM_Call using $cmd" {
set rd [valkey_deferring_client]
$rd $cmd blpop l 0
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {l a}
wait_for_blocked_clients_count 0
$rd close
}
test "Brpop on async RM_Call using $cmd" {
set rd [valkey_deferring_client]
$rd $cmd brpop l 0
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {l a}
wait_for_blocked_clients_count 0
$rd close
}
test "Brpoplpush on async RM_Call using $cmd" {
set rd [valkey_deferring_client]
$rd $cmd brpoplpush l1 l2 0
wait_for_blocked_clients_count 1
r lpush l1 a
assert_equal [$rd read] {a}
wait_for_blocked_clients_count 0
$rd close
r lpop l2
} {a}
test "Blmove on async RM_Call using $cmd" {
set rd [valkey_deferring_client]
$rd $cmd blmove l1 l2 LEFT LEFT 0
wait_for_blocked_clients_count 1
r lpush l1 a
assert_equal [$rd read] {a}
wait_for_blocked_clients_count 0
$rd close
r lpop l2
} {a}
test "Bzpopmin on async RM_Call using $cmd" {
set rd [valkey_deferring_client]
$rd $cmd bzpopmin s 0
wait_for_blocked_clients_count 1
r zadd s 10 foo
assert_equal [$rd read] {s foo 10}
wait_for_blocked_clients_count 0
$rd close
}
test "Bzpopmax on async RM_Call using $cmd" {
set rd [valkey_deferring_client]
$rd $cmd bzpopmax s 0
wait_for_blocked_clients_count 1
r zadd s 10 foo
assert_equal [$rd read] {s foo 10}
wait_for_blocked_clients_count 0
$rd close
}
}
test {Nested async RM_Call} {
set rd [valkey_deferring_client]
$rd do_rm_call_async do_rm_call_async do_rm_call_async do_rm_call_async blpop l 0
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {l a}
wait_for_blocked_clients_count 0
$rd close
}
test {Test multiple async RM_Call waiting on the same event} {
set rd1 [valkey_deferring_client]
set rd2 [valkey_deferring_client]
$rd1 do_rm_call_async do_rm_call_async do_rm_call_async do_rm_call_async blpop l 0
$rd2 do_rm_call_async do_rm_call_async do_rm_call_async do_rm_call_async blpop l 0
wait_for_blocked_clients_count 2
r lpush l element element
assert_equal [$rd1 read] {l element}
assert_equal [$rd2 read] {l element}
wait_for_blocked_clients_count 0
$rd1 close
$rd2 close
}
test {async RM_Call calls RM_Call} {
assert_equal {PONG} [r do_rm_call_async do_rm_call ping]
}
test {async RM_Call calls background RM_Call calls RM_Call} {
assert_equal {PONG} [r do_rm_call_async do_bg_rm_call do_rm_call ping]
}
test {async RM_Call calls background RM_Call calls RM_Call calls async RM_Call} {
assert_equal {PONG} [r do_rm_call_async do_bg_rm_call do_rm_call do_rm_call_async ping]
}
test {async RM_Call inside async RM_Call callback} {
set rd [valkey_deferring_client]
$rd wait_and_do_rm_call blpop l 0
wait_for_blocked_clients_count 1
start_server {} {
test "Connect a replica to the master instance" {
r slaveof [srv -1 host] [srv -1 port]
wait_for_condition 50 100 {
[s role] eq {slave} &&
[string match {*master_link_status:up*} [r info replication]]
} else {
fail "Can't turn the instance into a replica"
}
}
assert_equal {1} [r -1 lpush l a]
assert_equal [$rd read] {l a}
}
wait_for_blocked_clients_count 0
$rd close
}
test {Become replica while having async RM_Call running} {
r flushall
set rd [valkey_deferring_client]
$rd do_rm_call_async blpop l 0
wait_for_blocked_clients_count 1
#become a replica of a not existing server
r replicaof localhost 30000
catch {[$rd read]} e
assert_match {UNBLOCKED force unblock from blocking operation*} $e
wait_for_blocked_clients_count 0
r replicaof no one
r lpush l 1
# make sure the async rm_call was aborted
assert_equal [r llen l] {1}
$rd close
}
test {Pipeline with blocking RM_Call} {
r flushall
set rd [valkey_deferring_client]
set buf ""
append buf "do_rm_call_async blpop l 0\r\n"
append buf "ping\r\n"
$rd write $buf
$rd flush
wait_for_blocked_clients_count 1
# release the blocked client
r lpush l 1
assert_equal [$rd read] {l 1}
assert_equal [$rd read] {PONG}
wait_for_blocked_clients_count 0
$rd close
}
test {blocking RM_Call abort} {
r flushall
set rd [valkey_deferring_client]
$rd client id
set client_id [$rd read]
$rd do_rm_call_async blpop l 0
wait_for_blocked_clients_count 1
r client kill ID $client_id
assert_error {*error reading reply*} {$rd read}
wait_for_blocked_clients_count 0
r lpush l 1
# make sure the async rm_call was aborted
assert_equal [r llen l] {1}
$rd close
}
}
start_server {tags {"modules"}} {
r module load $testmodule
test {Test basic replication stream on unblock handler} {
r flushall
set repl [attach_to_replication_stream]
set rd [valkey_deferring_client]
$rd do_rm_call_async blpop l 0
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {l a}
assert_replication_stream $repl {
{select *}
{lpush l a}
{lpop l}
}
close_replication_stream $repl
wait_for_blocked_clients_count 0
$rd close
}
test {Test unblock handler are executed as a unit} {
r flushall
set repl [attach_to_replication_stream]
set rd [valkey_deferring_client]
$rd blpop_and_set_multiple_keys l x 1 y 2
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {OK}
assert_replication_stream $repl {
{select *}
{lpush l a}
{multi}
{lpop l}
{set x 1}
{set y 2}
{exec}
}
close_replication_stream $repl
wait_for_blocked_clients_count 0
$rd close
}
test {Test no propagation of blocking command} {
r flushall
set repl [attach_to_replication_stream]
set rd [valkey_deferring_client]
$rd do_rm_call_async_no_replicate blpop l 0
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {l a}
# make sure the lpop are not replicated
r set x 1
assert_replication_stream $repl {
{select *}
{lpush l a}
{set x 1}
}
close_replication_stream $repl
wait_for_blocked_clients_count 0
$rd close
}
}
start_server {tags {"modules"}} {
r module load $testmodule
r module load $testmodule2
test {Test unblock handler are executed as a unit with key space notifications} {
r flushall
set repl [attach_to_replication_stream]
set rd [valkey_deferring_client]
$rd blpop_and_set_multiple_keys l string_foo 1 string_bar 2
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {OK}
# Explanation of the first multi exec block:
# {lpop l} - pop the value by our blocking command 'blpop_and_set_multiple_keys'
# {set string_foo 1} - the action of our blocking command 'blpop_and_set_multiple_keys'
# {set string_bar 2} - the action of our blocking command 'blpop_and_set_multiple_keys'
# {incr string_changed{string_foo}} - post notification job that was registered when 'string_foo' changed
# {incr string_changed{string_bar}} - post notification job that was registered when 'string_bar' changed
# {incr string_total} - post notification job that was registered when string_changed{string_foo} changed
# {incr string_total} - post notification job that was registered when string_changed{string_bar} changed
assert_replication_stream $repl {
{select *}
{lpush l a}
{multi}
{lpop l}
{set string_foo 1}
{set string_bar 2}
{incr string_changed{string_foo}}
{incr string_changed{string_bar}}
{incr string_total}
{incr string_total}
{exec}
}
close_replication_stream $repl
wait_for_blocked_clients_count 0
$rd close
}
test {Test unblock handler are executed as a unit with lazy expire} {
r flushall
r DEBUG SET-ACTIVE-EXPIRE 0
set repl [attach_to_replication_stream]
set rd [valkey_deferring_client]
$rd blpop_and_set_multiple_keys l string_foo 1 string_bar 2
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {OK}
# set expiration on string_foo
r pexpire string_foo 1
after 10
# now the key should have been expired
$rd blpop_and_set_multiple_keys l string_foo 1 string_bar 2
wait_for_blocked_clients_count 1
r lpush l a
assert_equal [$rd read] {OK}
# Explanation of the first multi exec block:
# {lpop l} - pop the value by our blocking command 'blpop_and_set_multiple_keys'
# {set string_foo 1} - the action of our blocking command 'blpop_and_set_multiple_keys'
# {set string_bar 2} - the action of our blocking command 'blpop_and_set_multiple_keys'
# {incr string_changed{string_foo}} - post notification job that was registered when 'string_foo' changed
# {incr string_changed{string_bar}} - post notification job that was registered when 'string_bar' changed
# {incr string_total} - post notification job that was registered when string_changed{string_foo} changed
# {incr string_total} - post notification job that was registered when string_changed{string_bar} changed
#
# Explanation of the second multi exec block:
# {lpop l} - pop the value by our blocking command 'blpop_and_set_multiple_keys'
# {unlink string_foo} - lazy expiration of string_foo when 'blpop_and_set_multiple_keys' tries to write to it.
# {set string_foo 1} - the action of our blocking command 'blpop_and_set_multiple_keys'
# {set string_bar 2} - the action of our blocking command 'blpop_and_set_multiple_keys'
# {incr expired} - the post notification job, registered after string_foo got expired
# {incr string_changed{string_foo}} - post notification job triggered when we set string_foo
# {incr string_changed{string_bar}} - post notification job triggered when we set string_bar
# {incr string_total} - post notification job triggered when we incr 'string_changed{string_foo}'
# {incr string_total} - post notification job triggered when we incr 'string_changed{string_bar}'
assert_replication_stream $repl {
{select *}
{lpush l a}
{multi}
{lpop l}
{set string_foo 1}
{set string_bar 2}
{incr string_changed{string_foo}}
{incr string_changed{string_bar}}
{incr string_total}
{incr string_total}
{exec}
{pexpireat string_foo *}
{lpush l a}
{multi}
{lpop l}
{unlink string_foo}
{set string_foo 1}
{set string_bar 2}
{incr expired}
{incr string_changed{string_foo}}
{incr string_changed{string_bar}}
{incr string_total}
{incr string_total}
{exec}
}
close_replication_stream $repl
r DEBUG SET-ACTIVE-EXPIRE 1
wait_for_blocked_clients_count 0
$rd close
}
}
start_server {tags {"modules"}} {
r module load $testmodule
r module load $testmodule3
test {Test unblock handler on module blocked on keys} {
set rd [valkey_deferring_client]
r fsl.push l 1
$rd do_rm_call_async FSL.BPOPGT l 3 0
wait_for_blocked_clients_count 1
r fsl.push l 2
r fsl.push l 3
r fsl.push l 4
assert_equal [$rd read] {4}
wait_for_blocked_clients_count 0
$rd close
}
}