@@ -850,6 +850,97 @@ Y_UNIT_TEST_SUITE(TSubscriberSyncQuorumTest) {
850
850
UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Get ()->Partial , true , syncResponse->ToString ());
851
851
}
852
852
}
853
+
854
+ Y_UNIT_TEST (ReconfigurationWithDelayedSyncRequest) {
855
+ TTestBasicRuntime runtime;
856
+ SetupMinimalRuntime (runtime);
857
+
858
+ runtime.SetLogPriority (NKikimrServices::SCHEME_BOARD_SUBSCRIBER, NLog::PRI_DEBUG);
859
+
860
+ const auto stateStorageInfo = GetStateStorageInfo (runtime);
861
+ const auto participatingReplicas = CountParticipatingReplicas (*stateStorageInfo);
862
+
863
+ constexpr int DomainId = 1 ;
864
+ constexpr const char * Path = " TestPath" ;
865
+ const TActorId edge = runtime.AllocateEdgeActor ();
866
+
867
+ const TActorId subscriber = runtime.Register (CreateSchemeBoardSubscriber (edge, Path, DomainId));
868
+ TBlockEvents<NInternalEvents::TEvNotify> notificationBlocker (runtime, [&](const NInternalEvents::TEvNotify::TPtr& ev) {
869
+ return ev->Recipient == subscriber;
870
+ });
871
+ runtime.WaitFor (" initial path lookups" , [&]() {
872
+ return notificationBlocker.size () == participatingReplicas;
873
+ }, TDuration::Seconds (10 ));
874
+
875
+ // Send sync request: subscriber will queue it in DelayedSyncRequest since it cannot process syncs before finishing its initialization.
876
+ constexpr ui64 cookie = 12345 ;
877
+ runtime.Send (new IEventHandle (subscriber, edge, new NInternalEvents::TEvSyncRequest (), 0 , cookie));
878
+
879
+ auto replicas = ResolveReplicas (runtime, Path);
880
+ runtime.Send (subscriber, edge, replicas->Release ().Release ());
881
+
882
+ // Now allow all notifications through so that initialization completes.
883
+ notificationBlocker.Stop ().Unblock ();
884
+
885
+ auto syncResponse = runtime.GrabEdgeEvent <NInternalEvents::TEvSyncResponse>(edge, TDuration::Seconds (10 ));
886
+ UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Get ()->Path , Path, syncResponse->ToString ());
887
+ UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Cookie , cookie, syncResponse->ToString ());
888
+ UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Get ()->Partial , false , syncResponse->ToString ());
889
+
890
+ // No additional sync responses.
891
+ UNIT_CHECK_GENERATED_EXCEPTION (
892
+ runtime.GrabEdgeEvent <NInternalEvents::TEvSyncResponse>(edge, TDuration::Seconds (10 )),
893
+ TEmptyEventQueueException
894
+ );
895
+ }
896
+
897
+ Y_UNIT_TEST (ReconfigurationWithCurrentSyncRequest) {
898
+ TTestBasicRuntime runtime;
899
+ SetupMinimalRuntime (runtime);
900
+
901
+ runtime.SetLogPriority (NKikimrServices::SCHEME_BOARD_SUBSCRIBER, NLog::PRI_DEBUG);
902
+
903
+ const auto stateStorageInfo = GetStateStorageInfo (runtime);
904
+ const auto participatingReplicas = CountParticipatingReplicas (*stateStorageInfo);
905
+
906
+ constexpr int DomainId = 1 ;
907
+ constexpr const char * Path = " TestPath" ;
908
+ const TActorId edge = runtime.AllocateEdgeActor ();
909
+
910
+ const TActorId subscriber = runtime.Register (CreateSchemeBoardSubscriber (edge, Path, DomainId));
911
+ TBlockEvents<NInternalEvents::TEvNotify> notificationBlocker (runtime, [&](const NInternalEvents::TEvNotify::TPtr& ev) {
912
+ return ev->Recipient == subscriber;
913
+ });
914
+ runtime.WaitFor (" initial path lookups" , [&]() {
915
+ return notificationBlocker.size () == participatingReplicas;
916
+ }, TDuration::Seconds (10 ));
917
+ notificationBlocker.Stop ().Unblock ();
918
+
919
+ constexpr ui64 cookie = 12345 ;
920
+ TBlockEvents<NInternalEvents::TEvSyncVersionResponse> syncResponseBlocker (runtime, [&](const NInternalEvents::TEvSyncVersionResponse::TPtr& ev) {
921
+ return ev->Recipient == subscriber && ev->Cookie == cookie;
922
+ });
923
+ runtime.Send (new IEventHandle (subscriber, edge, new NInternalEvents::TEvSyncRequest (), 0 , cookie));
924
+ runtime.WaitFor (" some sync responses" , [&]() {
925
+ return !syncResponseBlocker.empty ();
926
+ }, TDuration::Seconds (10 ));
927
+ syncResponseBlocker.Unblock (1 );
928
+
929
+ auto replicas = ResolveReplicas (runtime, Path);
930
+ runtime.Send (subscriber, edge, replicas->Release ().Release ());
931
+ syncResponseBlocker.Stop ().Unblock ();
932
+
933
+ auto syncResponse = runtime.GrabEdgeEvent <NInternalEvents::TEvSyncResponse>(edge, TDuration::Seconds (10 ));
934
+ UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Get ()->Path , Path, syncResponse->ToString ());
935
+ UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Cookie , cookie, syncResponse->ToString ());
936
+ UNIT_ASSERT_VALUES_EQUAL_C (syncResponse->Get ()->Partial , true , syncResponse->ToString ());
937
+
938
+ // No additional sync responses.
939
+ UNIT_CHECK_GENERATED_EXCEPTION (
940
+ runtime.GrabEdgeEvent <NInternalEvents::TEvSyncResponse>(edge, TDuration::Seconds (10 )),
941
+ TEmptyEventQueueException
942
+ );
943
+ }
853
944
}
854
945
855
946
} // NSchemeBoard
0 commit comments