mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
20533cc1d7
In order to speed up tests, avoid saving an RDB (mostly notable on shutdown), except for tests that explicitly test the RDB mechanism In addition, use `shutdown-on-sigterm force` to prevetn shutdown from failing in case the server is in the middle of the initial AOFRW Also a a test that checks that the `shutdown-on-sigterm default` is to refuse shutdown if there's an initial AOFRW Co-authored-by: Guy Benoish <guy.benoish@redislabs.com>
307 lines
15 KiB
Tcl
307 lines
15 KiB
Tcl
# This module can be configure with multiple options given as flags on module load time
|
|
# 0 - not aux fields will be declared (this is the default)
|
|
# 1 << 0 - use aux_save2 api
|
|
# 1 << 1 - call aux callback before key space
|
|
# 1 << 2 - call aux callback after key space
|
|
# 1 << 3 - do not save data on aux callback
|
|
set testmodule [file normalize tests/modules/testrdb.so]
|
|
|
|
tags "modules" {
|
|
test {modules are able to persist types} {
|
|
start_server [list overrides [list loadmodule "$testmodule"]] {
|
|
r testrdb.set.key key1 value1
|
|
assert_equal "value1" [r testrdb.get.key key1]
|
|
r debug reload
|
|
assert_equal "value1" [r testrdb.get.key key1]
|
|
}
|
|
}
|
|
|
|
test {modules global are lost without aux} {
|
|
set server_path [tmpdir "server.module-testrdb"]
|
|
start_server [list overrides [list loadmodule "$testmodule" "dir" $server_path] keep_persistence true] {
|
|
r testrdb.set.before global1
|
|
assert_equal "global1" [r testrdb.get.before]
|
|
}
|
|
start_server [list overrides [list loadmodule "$testmodule" "dir" $server_path]] {
|
|
assert_equal "" [r testrdb.get.before]
|
|
}
|
|
}
|
|
|
|
test {aux that saves no data are not saved to the rdb when aux_save2 is used} {
|
|
set server_path [tmpdir "server.module-testrdb"]
|
|
puts $server_path
|
|
# 15 == 1111 - use aux_save2 before and after key space without data
|
|
start_server [list overrides [list loadmodule "$testmodule 15" "dir" $server_path] keep_persistence true] {
|
|
r set x 1
|
|
r save
|
|
}
|
|
start_server [list overrides [list "dir" $server_path] keep_persistence true] {
|
|
# make sure server started successfully without the module.
|
|
assert_equal {1} [r get x]
|
|
}
|
|
}
|
|
|
|
test {aux that saves no data are saved to the rdb when aux_save is used} {
|
|
set server_path [tmpdir "server.module-testrdb"]
|
|
puts $server_path
|
|
# 14 == 1110 - use aux_save before and after key space without data
|
|
start_server [list overrides [list loadmodule "$testmodule 14" "dir" $server_path] keep_persistence true] {
|
|
r set x 1
|
|
r save
|
|
}
|
|
start_server [list overrides [list loadmodule "$testmodule 14" "dir" $server_path] keep_persistence true] {
|
|
# make sure server started successfully and aux_save was called twice.
|
|
assert_equal {1} [r get x]
|
|
assert_equal {2} [r testrdb.get.n_aux_load_called]
|
|
}
|
|
}
|
|
|
|
foreach test_case {6 7} {
|
|
# 6 == 0110 - use aux_save before and after key space with data
|
|
# 7 == 0111 - use aux_save2 before and after key space with data
|
|
test {modules are able to persist globals before and after} {
|
|
set server_path [tmpdir "server.module-testrdb"]
|
|
start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"] keep_persistence true] {
|
|
r testrdb.set.before global1
|
|
r testrdb.set.after global2
|
|
assert_equal "global1" [r testrdb.get.before]
|
|
assert_equal "global2" [r testrdb.get.after]
|
|
}
|
|
start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"]] {
|
|
assert_equal "global1" [r testrdb.get.before]
|
|
assert_equal "global2" [r testrdb.get.after]
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
foreach test_case {4 5} {
|
|
# 4 == 0100 - use aux_save after key space with data
|
|
# 5 == 0101 - use aux_save2 after key space with data
|
|
test {modules are able to persist globals just after} {
|
|
set server_path [tmpdir "server.module-testrdb"]
|
|
start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"] keep_persistence true] {
|
|
r testrdb.set.after global2
|
|
assert_equal "global2" [r testrdb.get.after]
|
|
}
|
|
start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"]] {
|
|
assert_equal "global2" [r testrdb.get.after]
|
|
}
|
|
}
|
|
}
|
|
|
|
test {Verify module options info} {
|
|
start_server [list overrides [list loadmodule "$testmodule"]] {
|
|
assert_match "*\[handle-io-errors|handle-repl-async-load\]*" [r info modules]
|
|
}
|
|
}
|
|
|
|
tags {repl} {
|
|
test {diskless loading short read with module} {
|
|
start_server [list overrides [list loadmodule "$testmodule"]] {
|
|
set replica [srv 0 client]
|
|
set replica_host [srv 0 host]
|
|
set replica_port [srv 0 port]
|
|
start_server [list overrides [list loadmodule "$testmodule"]] {
|
|
set master [srv 0 client]
|
|
set master_host [srv 0 host]
|
|
set master_port [srv 0 port]
|
|
|
|
# Set master and replica to use diskless replication
|
|
$master config set repl-diskless-sync yes
|
|
$master config set rdbcompression no
|
|
$replica config set repl-diskless-load swapdb
|
|
$master config set hz 500
|
|
$replica config set hz 500
|
|
$master config set dynamic-hz no
|
|
$replica config set dynamic-hz no
|
|
set start [clock clicks -milliseconds]
|
|
for {set k 0} {$k < 30} {incr k} {
|
|
r testrdb.set.key key$k [string repeat A [expr {int(rand()*1000000)}]]
|
|
}
|
|
|
|
if {$::verbose} {
|
|
set end [clock clicks -milliseconds]
|
|
set duration [expr $end - $start]
|
|
puts "filling took $duration ms (TODO: use pipeline)"
|
|
set start [clock clicks -milliseconds]
|
|
}
|
|
|
|
# Start the replication process...
|
|
set loglines [count_log_lines -1]
|
|
$master config set repl-diskless-sync-delay 0
|
|
$replica replicaof $master_host $master_port
|
|
|
|
# kill the replication at various points
|
|
set attempts 100
|
|
if {$::accurate} { set attempts 500 }
|
|
for {set i 0} {$i < $attempts} {incr i} {
|
|
# wait for the replica to start reading the rdb
|
|
# using the log file since the replica only responds to INFO once in 2mb
|
|
set res [wait_for_log_messages -1 {"*Loading DB in memory*"} $loglines 2000 1]
|
|
set loglines [lindex $res 1]
|
|
|
|
# add some additional random sleep so that we kill the master on a different place each time
|
|
after [expr {int(rand()*50)}]
|
|
|
|
# kill the replica connection on the master
|
|
set killed [$master client kill type replica]
|
|
|
|
set res [wait_for_log_messages -1 {"*Internal error in RDB*" "*Finished with success*" "*Successful partial resynchronization*"} $loglines 500 10]
|
|
if {$::verbose} { puts $res }
|
|
set log_text [lindex $res 0]
|
|
set loglines [lindex $res 1]
|
|
if {![string match "*Internal error in RDB*" $log_text]} {
|
|
# force the replica to try another full sync
|
|
$master multi
|
|
$master client kill type replica
|
|
$master set asdf asdf
|
|
# fill replication backlog with new content
|
|
$master config set repl-backlog-size 16384
|
|
for {set keyid 0} {$keyid < 10} {incr keyid} {
|
|
$master set "$keyid string_$keyid" [string repeat A 16384]
|
|
}
|
|
$master exec
|
|
}
|
|
|
|
# wait for loading to stop (fail)
|
|
# After a loading successfully, next loop will enter `async_loading`
|
|
wait_for_condition 1000 1 {
|
|
[s -1 async_loading] eq 0 &&
|
|
[s -1 loading] eq 0
|
|
} else {
|
|
fail "Replica didn't disconnect"
|
|
}
|
|
}
|
|
if {$::verbose} {
|
|
set end [clock clicks -milliseconds]
|
|
set duration [expr $end - $start]
|
|
puts "test took $duration ms"
|
|
}
|
|
# enable fast shutdown
|
|
$master config set rdb-key-save-delay 0
|
|
}
|
|
}
|
|
}
|
|
|
|
# Module events for diskless load swapdb when async_loading (matching master replid)
|
|
foreach test_case {6 7} {
|
|
# 6 == 0110 - use aux_save before and after key space with data
|
|
# 7 == 0111 - use aux_save2 before and after key space with data
|
|
foreach testType {Successful Aborted} {
|
|
start_server [list overrides [list loadmodule "$testmodule $test_case"] tags [list external:skip]] {
|
|
set replica [srv 0 client]
|
|
set replica_host [srv 0 host]
|
|
set replica_port [srv 0 port]
|
|
set replica_log [srv 0 stdout]
|
|
start_server [list overrides [list loadmodule "$testmodule $test_case"]] {
|
|
set master [srv 0 client]
|
|
set master_host [srv 0 host]
|
|
set master_port [srv 0 port]
|
|
|
|
set start [clock clicks -milliseconds]
|
|
|
|
# Set master and replica to use diskless replication on swapdb mode
|
|
$master config set repl-diskless-sync yes
|
|
$master config set repl-diskless-sync-delay 0
|
|
$master config set save ""
|
|
$replica config set repl-diskless-load swapdb
|
|
$replica config set save ""
|
|
|
|
# Initial sync to have matching replids between master and replica
|
|
$replica replicaof $master_host $master_port
|
|
|
|
# Let replica finish initial sync with master
|
|
wait_for_condition 100 100 {
|
|
[s -1 master_link_status] eq "up"
|
|
} else {
|
|
fail "Master <-> Replica didn't finish sync"
|
|
}
|
|
|
|
# Set global values on module so we can check if module event callbacks will pick it up correctly
|
|
$master testrdb.set.before value1_master
|
|
$replica testrdb.set.before value1_replica
|
|
|
|
# Put different data sets on the master and replica
|
|
# We need to put large keys on the master since the replica replies to info only once in 2mb
|
|
$replica debug populate 200 slave 10
|
|
$master debug populate 1000 master 100000
|
|
$master config set rdbcompression no
|
|
|
|
# Force the replica to try another full sync (this time it will have matching master replid)
|
|
$master multi
|
|
$master client kill type replica
|
|
# Fill replication backlog with new content
|
|
$master config set repl-backlog-size 16384
|
|
for {set keyid 0} {$keyid < 10} {incr keyid} {
|
|
$master set "$keyid string_$keyid" [string repeat A 16384]
|
|
}
|
|
$master exec
|
|
|
|
switch $testType {
|
|
"Aborted" {
|
|
# Set master with a slow rdb generation, so that we can easily intercept loading
|
|
# 10ms per key, with 1000 keys is 10 seconds
|
|
$master config set rdb-key-save-delay 10000
|
|
|
|
test {Diskless load swapdb RedisModuleEvent_ReplAsyncLoad handling: during loading, can keep module variable same as before} {
|
|
# Wait for the replica to start reading the rdb and module for acknowledgement
|
|
# We wanna abort only after the temp db was populated by REDISMODULE_AUX_BEFORE_RDB
|
|
wait_for_condition 100 100 {
|
|
[s -1 async_loading] eq 1 && [$replica testrdb.async_loading.get.before] eq "value1_master"
|
|
} else {
|
|
fail "Module didn't receive or react to REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED"
|
|
}
|
|
|
|
assert_equal [$replica dbsize] 200
|
|
assert_equal value1_replica [$replica testrdb.get.before]
|
|
}
|
|
|
|
# Make sure that next sync will not start immediately so that we can catch the replica in between syncs
|
|
$master config set repl-diskless-sync-delay 5
|
|
|
|
# Kill the replica connection on the master
|
|
set killed [$master client kill type replica]
|
|
|
|
test {Diskless load swapdb RedisModuleEvent_ReplAsyncLoad handling: when loading aborted, can keep module variable same as before} {
|
|
# Wait for loading to stop (fail) and module for acknowledgement
|
|
wait_for_condition 100 100 {
|
|
[s -1 async_loading] eq 0 && [$replica testrdb.async_loading.get.before] eq ""
|
|
} else {
|
|
fail "Module didn't receive or react to REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED"
|
|
}
|
|
|
|
assert_equal [$replica dbsize] 200
|
|
assert_equal value1_replica [$replica testrdb.get.before]
|
|
}
|
|
|
|
# Speed up shutdown
|
|
$master config set rdb-key-save-delay 0
|
|
}
|
|
"Successful" {
|
|
# Let replica finish sync with master
|
|
wait_for_condition 100 100 {
|
|
[s -1 master_link_status] eq "up"
|
|
} else {
|
|
fail "Master <-> Replica didn't finish sync"
|
|
}
|
|
|
|
test {Diskless load swapdb RedisModuleEvent_ReplAsyncLoad handling: after db loaded, can set module variable with new value} {
|
|
assert_equal [$replica dbsize] 1010
|
|
assert_equal value1_master [$replica testrdb.get.before]
|
|
}
|
|
}
|
|
}
|
|
|
|
if {$::verbose} {
|
|
set end [clock clicks -milliseconds]
|
|
set duration [expr $end - $start]
|
|
puts "test took $duration ms"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|