@@ -20,7 +20,8 @@ all() ->
2020
2121all_tests () ->
2222 [
23- basics
23+ basics ,
24+ snapshot_replication
2425 ].
2526
2627groups () ->
@@ -56,6 +57,71 @@ end_per_testcase(_TestCase, _Config) ->
5657% %%===================================================================
5758
5859
60+ snapshot_replication (_Config ) ->
61+ Members = [{kv1 , node ()}, {kv2 , node ()}],
62+ KvId = hd (Members ),
63+ {ok , _ , _ } = ra_kv :start_cluster (? SYS , ? FUNCTION_NAME ,
64+ #{members => Members }),
65+ ra :transfer_leadership (KvId , KvId ),
66+ {ok , #{}} = ra_kv :put (KvId , <<" k1" >>, <<" k1-value01" >>, 5000 ),
67+ % % write 10k entries of the same key
68+ [{ok , #{}} = ra_kv :put (KvId , integer_to_binary (I ), I , 5000 )
69+ || I <- lists :seq (1 , 5000 )],
70+
71+ ? assertMatch ({ok , #{machine := #{num_keys := _ }}, KvId },
72+ ra :member_overview (KvId )),
73+ ra_log_wal :force_roll_over (ra_log_wal ),
74+ % % wait for rollover processing
75+ ra_log_wal :last_writer_seq (ra_log_wal , <<>>),
76+ % % wait for segment writer to process
77+ ra_log_segment_writer :await (ra_log_segment_writer ),
78+ % % promt ra_kv to take a snapshot
79+ ok = ra :aux_command (KvId , take_snapshot ),
80+ ok = ra_lib :retry (
81+ fun () ->
82+ {ok , #{log := #{snapshot_index := SnapIdx ,
83+ last_index := LastIdx }}, _ } =
84+ ra :member_overview (KvId ),
85+ SnapIdx == LastIdx
86+ end , 100 , 100 ),
87+
88+ KvId3 = {kv3 , node ()},
89+ ok = ra_kv :add_member (? SYS , KvId3 , KvId ),
90+ KvId3Pid = whereis (kv3 ),
91+ ? assert (is_pid (KvId3Pid )),
92+ {ok , #{}} = ra_kv :put (KvId , <<" k3" >>, <<" k3-value" >>, 5000 ),
93+ {ok , #{}} = ra_kv :put (KvId , <<" k4" >>, <<" k4-value" >>, 5000 ),
94+ ok = ra :aux_command (KvId , take_snapshot ),
95+ % timer:sleep(1000),
96+ {ok , #{log := #{last_index := Kv1LastIndex }}, _ } = ra :member_overview (KvId ),
97+ ok = ra_lib :retry (
98+ fun () ->
99+ {ok , #{log := #{last_index := LastIdx }}, _ } =
100+ ra :member_overview (KvId3 ),
101+ Kv1LastIndex == LastIdx
102+ end , 100 , 100 ),
103+ ct :pal (" counters ~p " , [ra_counters :counters (KvId3 , [last_applied ])]),
104+ % % ensure kv3 did not crash during snapshot replication
105+ ? assertEqual (KvId3Pid , whereis (kv3 )),
106+
107+ ok = ra :stop_server (default , KvId3 ),
108+
109+ {ok , #{}} = ra_kv :put (KvId , <<" k5" >>, <<" k5-value" >>, 5000 ),
110+ {ok , #{}} = ra_kv :put (KvId , <<" k6" >>, <<" k6-value" >>, 5000 ),
111+ ok = ra :aux_command (KvId , take_snapshot ),
112+
113+ ok = ra :restart_server (default , KvId3 ),
114+ {ok , #{log := #{last_index := Kv1LastIndex2 }}, _ } = ra :member_overview (KvId ),
115+ ok = ra_lib :retry (
116+ fun () ->
117+ {ok , #{log := #{last_index := LastIdx }}, _ } =
118+ ra :member_overview (KvId3 ),
119+ Kv1LastIndex2 == LastIdx
120+ end , 100 , 100 ),
121+
122+ ra :delete_cluster ([KvId , {kv2 , node ()}, KvId3 ]),
123+ ok .
124+
59125basics (_Config ) ->
60126 Members = [{kv1 , node ()}],
61127 KvId = hd (Members ),
@@ -136,4 +202,5 @@ basics(_Config) ->
136202 undefined , 1000 ),
137203 ? assertEqual (Reads4 , Reads5 ),
138204 ct :pal (" counters ~p " , [ra_counters :overview (KvId )]),
205+ ra :delete_cluster ([KvId , KvId2 ]),
139206 ok .
0 commit comments