Skip to content

Commit b8ad08a

Browse files
test for scan consistency
Signed-off-by: Sarthak Aggarwal <[email protected]>
1 parent a646578 commit b8ad08a

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
start_server {tags {"scan-consistency-on-failover external:skip"}} {
2+
3+
set fixed_seed "00112233445566778899aabbccddeeff"
4+
set shared_overrides [list appendonly no save "" db-hash-seed $fixed_seed]
5+
6+
start_server [list overrides $shared_overrides] {
7+
set primary_host [srv 0 host]
8+
set primary_port [srv 0 port]
9+
10+
start_server [list overrides $shared_overrides] {
11+
set replica_host [srv 0 host]
12+
set replica_port [srv 0 port]
13+
14+
set primary [srv -1 client]
15+
set replica [srv 0 client]
16+
17+
$primary flushall
18+
$replica replicaof $primary_host $primary_port
19+
20+
wait_for_sync $replica 200 50
21+
22+
set n 2000
23+
for {set i 0} {$i < $n} {incr i} {
24+
$primary set "k:$i" x
25+
}
26+
for {set i 0} {$i < $n} {incr i} {
27+
$primary sadd s "m:$i"
28+
$primary hset h "f:$i" v
29+
$primary zadd z $i "z:$i"
30+
}
31+
32+
wait_for_condition 200 50 {
33+
[$replica dbsize] == [$primary dbsize]
34+
} else {
35+
fail "replica did not catch up dbsize"
36+
}
37+
38+
# ensuring both instances have finished rehashing.
39+
wait_for_condition 200 50 {
40+
![string match {Hash table 1 stats} [$primary debug htstats 0]] &&
41+
![string match {Hash table 1 stats} [$replica debug htstats 0]]
42+
} else {
43+
fail "hash tables still rehashing"
44+
}
45+
46+
# SCAN across failover
47+
set cur 0
48+
set steps 0
49+
set seen {}
50+
51+
while {1} {
52+
set res [$primary scan $cur count 100]
53+
set cur [lindex $res 0]
54+
set keys [lindex $res 1]
55+
foreach k $keys {
56+
if {[string match "k:*" $k]} {
57+
dict set seen $k 1
58+
}
59+
}
60+
incr steps
61+
62+
# After a few pages, promote the replica
63+
if {$steps == 5} {
64+
$replica replicaof no one
65+
wait_for_condition 100 50 {
66+
([string match {*master*} [$replica info replication]])
67+
} else {
68+
fail "replica did not promote to master"
69+
}
70+
break
71+
}
72+
}
73+
74+
set resume_cur $cur
75+
76+
# Resume SCAN on the new primary using the SAME cursor.
77+
if {$resume_cur ne "0"} {
78+
set res [$replica scan $resume_cur count 100]
79+
set cur [lindex $res 0]
80+
set keys [lindex $res 1]
81+
foreach k $keys {
82+
if {[string match "k:*" $k]} {
83+
dict set seen $k 1
84+
}
85+
}
86+
}
87+
88+
# Perform a full SCAN sweep to ensure all keys are covered.
89+
set cur 0
90+
set failover_steps 0
91+
while {1} {
92+
set res [$replica scan $cur count 100]
93+
set cur [lindex $res 0]
94+
set keys [lindex $res 1]
95+
foreach k $keys {
96+
if {[string match "k:*" $k]} {
97+
dict set seen $k 1
98+
}
99+
}
100+
incr failover_steps
101+
if {$cur eq "0"} break
102+
103+
# safety guardrail incase scan doesn't end
104+
if {$failover_steps > 200} {
105+
fail "SCAN did not complete after failover"
106+
}
107+
}
108+
109+
set all_keys [$replica keys "k:*"]
110+
assert_equal $n [llength $all_keys]
111+
assert_equal [lsort $all_keys] [lsort [dict keys $seen]]
112+
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)