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 20
23+ for {set i 0} {$i < $n } {incr i} {
24+ $primary set " k:$i " x
25+ }
26+
27+ wait_for_condition 200 50 {
28+ [$replica dbsize] == [$primary dbsize]
29+ } else {
30+ fail " replica did not catch up dbsize"
31+ }
32+
33+ # ensuring both instances have finished rehashing.
34+ wait_for_condition 200 50 {
35+ ![string match {Hash table 1 stats} [$primary debug htstats 9]] &&
36+ ![string match {Hash table 1 stats} [$replica debug htstats 9]]
37+ } else {
38+ fail " hash tables still rehashing"
39+ }
40+
41+ assert_match [$primary config get db-hash-seed] [$replica config get db-hash-seed]
42+
43+ # SCAN across failover
44+ set cur 0
45+ set steps 0
46+ set seen {}
47+
48+ while {1} {
49+ set res [$primary scan $cur count 1]
50+ set cur [lindex $res 0]
51+ set keys [lindex $res 1]
52+ foreach k $keys {
53+ if {[string match " k:*" $k ]} {
54+ dict set seen $k 1
55+ }
56+ }
57+ incr steps
58+
59+ # After a few pages, promote the replica
60+ if {$steps == 5} {
61+ $replica replicaof no one
62+ wait_for_condition 100 50 {
63+ ([string match {*master*} [$replica info replication]])
64+ } else {
65+ fail " replica did not promote to master"
66+ }
67+ break
68+ }
69+ }
70+
71+ # Perform a full SCAN sweep to ensure all keys are covered.
72+ set failover_steps 0
73+ while {1} {
74+ set res [$replica scan $cur count 1]
75+ set cur [lindex $res 0]
76+ set keys [lindex $res 1]
77+ foreach k $keys {
78+ if {[string match " k:*" $k ]} {
79+ dict set seen $k 1
80+ }
81+ }
82+ incr failover_steps
83+ if {$cur eq " 0" } break
84+
85+ # safety guardrail incase scan doesn't end
86+ if {$failover_steps > 200} {
87+ fail " SCAN did not complete after failover"
88+ }
89+ }
90+
91+ set all_keys [$replica keys " k:*" ]
92+ assert_equal $n [llength $all_keys ]
93+ assert_equal [lsort $all_keys ] [lsort [dict keys $seen ]]
94+
95+ }
96+ }
97+ }
0 commit comments