@@ -48,6 +48,7 @@ all_tests() ->
48
48
add_member_without_quorum ,
49
49
force_start_follower_as_single_member ,
50
50
force_start_follower_as_single_member_nonvoter ,
51
+ force_start_nonvoter_as_single_member ,
51
52
initial_members_query
52
53
].
53
54
@@ -784,30 +785,80 @@ force_start_follower_as_single_member_nonvoter(Config) ->
784
785
ServerId4 = ? config (server_id4 , Config ),
785
786
UId4 = ? config (uid4 , Config ),
786
787
Conf4 = conf (ClusterName , UId4 , ServerId4 , PrivDir , [ServerId3 ]),
787
- {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId4 , membership => promotable , uid => << " test4 " >> }),
788
+ {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId4 , membership => promotable , uid => UId4 }),
788
789
% % the membership has changed but member not running yet
789
790
% % it is nonvoter and does not affect quorum size
790
791
{ok , _ , _ } = ra :process_command (ServerId3 , {enq , banana }),
791
792
% % start new member
792
- ok = ra :start_server (? SYS , Conf4 #{membership => promotable , uid => << " test4 " >> }),
793
+ ok = ra :start_server (? SYS , Conf4 #{membership => promotable , uid => UId4 }),
793
794
{ok , _ , ServerId3 } = ra :members (ServerId4 ),
794
795
ok = enqueue (ServerId3 , msg3 ),
795
796
796
797
% % add a non-voter member
797
798
ServerId5 = ? config (server_id5 , Config ),
798
799
UId5 = ? config (uid5 , Config ),
799
800
Conf5 = conf (ClusterName , UId5 , ServerId5 , PrivDir , [ServerId3 ]),
800
- {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId5 , membership => non_voter , uid => << " test5 " >> }),
801
+ {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId5 , membership => non_voter , uid => UId5 }),
801
802
% % the membership has changed but member not running yet
802
803
% % it is nonvoter and does not affect quorum size
803
804
{ok , _ , _ } = ra :process_command (ServerId3 , {enq , banana }),
804
805
% % start new member
805
- ok = ra :start_server (? SYS , Conf5 #{membership => non_voter , uid => << " test5 " >> }),
806
+ ok = ra :start_server (? SYS , Conf5 #{membership => non_voter , uid => UId5 }),
806
807
{ok , _ , ServerId3 } = ra :members (ServerId5 ),
807
808
ok = enqueue (ServerId3 , msg4 ),
808
809
809
810
ok .
810
811
812
+ force_start_nonvoter_as_single_member (Config ) ->
813
+ ok = logger :set_primary_config (level , all ),
814
+ ClusterName = ? config (cluster_name , Config ),
815
+ PrivDir = ? config (priv_dir , Config ),
816
+ ServerId1 = ? config (server_id , Config ),
817
+ ServerId2 = ? config (server_id2 , Config ),
818
+ ServerId3 = ? config (server_id3 , Config ),
819
+ InitialCluster = [ServerId1 , ServerId2 , ServerId3 ],
820
+ ok = start_cluster (ClusterName , InitialCluster ),
821
+ timer :sleep (100 ),
822
+
823
+ ServerId4 = ? config (server_id4 , Config ),
824
+ UId4 = ? config (uid4 , Config ),
825
+ Conf4 = conf (ClusterName , UId4 , ServerId4 , PrivDir , InitialCluster ),
826
+ {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId4 , membership => non_voter , uid => UId4 }),
827
+ ok = ra :start_server (? SYS , Conf4 #{membership => non_voter , uid => UId4 }),
828
+
829
+ % % stop voters to simulate permanent outage
830
+ ok = ra :stop_server (? SYS , ServerId1 ),
831
+ ok = ra :stop_server (? SYS , ServerId2 ),
832
+ ok = ra :stop_server (? SYS , ServerId3 ),
833
+ timer :sleep (100 ),
834
+
835
+ % % force the remaining node to change it's membership
836
+ ok = ra_server_proc :force_shrink_members_to_current_member (ServerId4 ),
837
+ {ok , [_ ], ServerId4 } = ra :members (ServerId4 ),
838
+ ok = enqueue (ServerId4 , msg1 ),
839
+
840
+ % % test that it works after restart
841
+ ok = ra :stop_server (? SYS , ServerId4 ),
842
+ ok = ra :restart_server (? SYS , ServerId4 ),
843
+ {ok , [_ ], ServerId4 } = ra :members (ServerId4 ),
844
+ ok = enqueue (ServerId4 , msg2 ),
845
+
846
+
847
+ % % add a non-voter member
848
+ ServerId5 = ? config (server_id5 , Config ),
849
+ UId5 = ? config (uid5 , Config ),
850
+ Conf5 = conf (ClusterName , UId5 , ServerId5 , PrivDir , [ServerId4 ]),
851
+ {ok , _ , _ } = ra :add_member (ServerId4 , #{id => ServerId5 , membership => non_voter , uid => UId5 }),
852
+ % % the membership has changed but member not running yet
853
+ % % it is nonvoter and does not affect quorum size
854
+ ok = enqueue (ServerId4 , msg3 ),
855
+ % % start new member
856
+ ok = ra :start_server (? SYS , Conf5 #{membership => non_voter , uid => UId5 }),
857
+ {ok , _ , ServerId4 } = ra :members (ServerId5 ),
858
+ ok = enqueue (ServerId4 , msg4 ),
859
+
860
+ ok .
861
+
811
862
initial_members_query (Config ) ->
812
863
ok = logger :set_primary_config (level , all ),
813
864
% % ra:start_server should fail if the node already exists
0 commit comments