@@ -76,6 +76,42 @@ class XClusterOutboundReplicationGroupTest : public XClusterYsqlTestBase {
7676 return table_info->id ();
7777 }
7878
79+ // Create a new OutboundReplicationGroup. Use GetXClusterStreams, or IsBootstrapRequired to wait
80+ // for the new group to be ready.
81+ Status CreateOutboundReplicationGroupAsync (
82+ const xcluster::ReplicationGroupId& replication_group_id,
83+ const std::vector<NamespaceId>& namespace_ids) {
84+ return XClusterClient ().CreateOutboundReplicationGroup (
85+ replication_group_id, namespace_ids, UseAutomaticMode ());
86+ }
87+
88+ Status CreateOutboundReplicationGroupSync (
89+ const xcluster::ReplicationGroupId& replication_group_id = kReplicationGroupId ,
90+ const std::vector<NamespaceId>& namespace_ids = {}) {
91+ auto namespace_ids_copy = namespace_ids;
92+ if (namespace_ids_copy.empty ()) {
93+ namespace_ids_copy.push_back (namespace_id_);
94+ }
95+
96+ RETURN_NOT_OK (CreateOutboundReplicationGroupAsync (replication_group_id, namespace_ids_copy));
97+ for (const auto & namespace_id : namespace_ids_copy) {
98+ RETURN_NOT_OK (GetXClusterStreams (replication_group_id, namespace_id));
99+ }
100+ return Status::OK ();
101+ }
102+
103+ Result<bool > IsBootstrapRequired (
104+ const xcluster::ReplicationGroupId& replication_group_id = kReplicationGroupId ,
105+ const NamespaceId& namespace_id = {}) {
106+ std::promise<Result<bool >> promise;
107+ RETURN_NOT_OK (XClusterClient ().IsBootstrapRequired (
108+ CoarseMonoClock::Now () + kDeadline , replication_group_id,
109+ namespace_id.empty () ? namespace_id_ : namespace_id,
110+ [&promise](Result<bool > result) { promise.set_value (std::move (result)); }));
111+
112+ return promise.get_future ().get ();
113+ }
114+
79115 // Cleanup streams marked for deletion and get the list of xcluster streams.
80116 std::unordered_set<xrepl::StreamId> CleanupAndGetAllXClusterStreams () {
81117 catalog_manager_->RunXReplBgTasks (epoch_);
@@ -132,7 +168,12 @@ class XClusterOutboundReplicationGroupTest : public XClusterYsqlTestBase {
132168 CoarseMonoClock::Now () + kDeadline , replication_group_id, namespace_id, table_names,
133169 pg_schema_names, [&promise](const auto & resp) { promise.set_value (resp); }));
134170
135- return promise.get_future ().get ();
171+ auto resp = VERIFY_RESULT (promise.get_future ().get ());
172+ if (resp.has_error ()) {
173+ return StatusFromPB (resp.error ().status ());
174+ }
175+
176+ return resp;
136177 }
137178
138179 Result<master::GetXClusterStreamsResponsePB> GetXClusterStreamsByTableId (
@@ -210,8 +251,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, TestMultipleTable) {
210251
211252 ASSERT_NOK (GetXClusterStreams (kReplicationGroupId , namespace_id_));
212253
213- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
214- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
254+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
215255
216256 auto resp = ASSERT_RESULT (GetXClusterStreams (kReplicationGroupId , namespace_id_));
217257
@@ -260,8 +300,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, AddDeleteNamespaces) {
260300 auto ns2_table_id_1 = ASSERT_RESULT (CreateYsqlTable (namespace_name_2, kTableName1 ));
261301 auto ns2_table_id_2 = ASSERT_RESULT (CreateYsqlTable (namespace_name_2, kTableName2 ));
262302
263- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
264- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
303+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
265304
266305 // Wait for the new streams to be ready.
267306 auto ns1_info = ASSERT_RESULT (GetXClusterStreams (kReplicationGroupId , namespace_id_));
@@ -324,11 +363,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, AddTable) {
324363 auto table_id_1 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName1 ));
325364 ASSERT_OK (VerifyWalRetentionOfTable (table_id_1, 900 ));
326365
327- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
328- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
329-
330- // Wait for the new streams to be ready.
331- ASSERT_OK (GetXClusterStreams (kReplicationGroupId , namespace_id_));
366+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
332367
333368 auto all_xcluster_streams_initial = CleanupAndGetAllXClusterStreams ();
334369 ASSERT_EQ (all_xcluster_streams_initial.size (), 1 + OverheadStreamsCount ());
@@ -349,17 +384,8 @@ TEST_F(XClusterOutboundReplicationGroupTest, IsBootstrapRequiredEmptyTable) {
349384 ANNOTATE_UNPROTECTED_WRITE (FLAGS_max_xcluster_streams_to_checkpoint_in_parallel) = 1 ;
350385
351386 auto table_id_1 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName1 ));
352- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
353- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
354-
355- std::promise<Result<bool >> promise;
356-
357- ASSERT_OK (XClusterClient ().IsBootstrapRequired (
358- CoarseMonoClock::Now () + kDeadline , kReplicationGroupId , namespace_id_,
359- [&promise](Result<bool > result) { promise.set_value (std::move (result)); }));
360-
361- auto is_bootstrap_required = ASSERT_RESULT (promise.get_future ().get ());
362- ASSERT_FALSE (is_bootstrap_required);
387+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
388+ ASSERT_FALSE (ASSERT_RESULT (IsBootstrapRequired ()));
363389}
364390
365391TEST_F (XClusterOutboundReplicationGroupTest, IsBootstrapRequiredTableWithData) {
@@ -371,17 +397,8 @@ TEST_F(XClusterOutboundReplicationGroupTest, IsBootstrapRequiredTableWithData) {
371397 ASSERT_OK (producer_client ()->OpenTable (table_id_2, &table_2));
372398 ASSERT_OK (InsertRowsInProducer (0 , 10 , table_2));
373399
374- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
375- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
376-
377- std::promise<Result<bool >> promise;
378-
379- ASSERT_OK (XClusterClient ().IsBootstrapRequired (
380- CoarseMonoClock::Now () + kDeadline , kReplicationGroupId , namespace_id_,
381- [&promise](Result<bool > result) { promise.set_value (std::move (result)); }));
382-
383- auto is_bootstrap_required = ASSERT_RESULT (promise.get_future ().get ());
384- ASSERT_TRUE (is_bootstrap_required);
400+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
401+ ASSERT_TRUE (ASSERT_RESULT (IsBootstrapRequired ()));
385402}
386403
387404TEST_F (XClusterOutboundReplicationGroupTest, IsBootstrapRequiredTableWithDeletedData) {
@@ -394,17 +411,9 @@ TEST_F(XClusterOutboundReplicationGroupTest, IsBootstrapRequiredTableWithDeleted
394411 ASSERT_OK (InsertRowsInProducer (0 , 10 , table_2));
395412 ASSERT_OK (DeleteRowsInProducer (0 , 10 , table_2));
396413
397- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
398- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
414+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
399415
400- std::promise<Result<bool >> promise;
401-
402- ASSERT_OK (XClusterClient ().IsBootstrapRequired (
403- CoarseMonoClock::Now () + kDeadline , kReplicationGroupId , namespace_id_,
404- [&promise](Result<bool > result) { promise.set_value (std::move (result)); }));
405-
406- auto is_bootstrap_required = ASSERT_RESULT (promise.get_future ().get ());
407- ASSERT_FALSE (is_bootstrap_required);
416+ ASSERT_FALSE (ASSERT_RESULT (IsBootstrapRequired ()));
408417}
409418
410419TEST_P (XClusterOutboundReplicationGroupParameterized, MasterRestartDuringCheckpoint) {
@@ -421,8 +430,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, MasterRestartDuringCheckpo
421430
422431 ANNOTATE_UNPROTECTED_WRITE (FLAGS_TEST_block_xcluster_checkpoint_namespace_task) = true ;
423432
424- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
425- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
433+ ASSERT_OK (CreateOutboundReplicationGroupAsync (kReplicationGroupId , {namespace_id_}));
426434
427435 std::promise<Result<master::GetXClusterStreamsResponsePB>> promise;
428436 auto future = promise.get_future ();
@@ -449,8 +457,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, Repair) {
449457 auto table_id_1 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName1 ));
450458 auto table_id_2 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName2 ));
451459
452- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
453- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
460+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
454461
455462 auto resp = ASSERT_RESULT (GetXClusterStreams (kReplicationGroupId , namespace_id_));
456463 ASSERT_EQ (resp.table_infos_size (), 2 + OverheadStreamsCount ());
@@ -546,8 +553,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, RepairWithYbAdmin) {
546553 auto table_id_1 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName1 ));
547554 auto table_id_2 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName2 ));
548555
549- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
550- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
556+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
551557
552558 auto resp = ASSERT_RESULT (GetXClusterStreams (kReplicationGroupId , namespace_id_));
553559 ASSERT_EQ (resp.table_infos_size (), 2 + OverheadStreamsCount ());
@@ -589,11 +595,8 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, TestListAPIs) {
589595 ASSERT_OK (CreateYsqlTable (namespace_name_2, " table_2" ));
590596
591597 // Replication group 1 with two namespaces.
592- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
593- kReplicationGroupId , {namespace_id_, namespace_id_2}, UseAutomaticMode ()));
594- // Wait for checkpointing to complete.
595- ASSERT_OK (GetXClusterStreams (kReplicationGroupId , namespace_id_));
596- ASSERT_OK (GetXClusterStreams (kReplicationGroupId , namespace_id_2));
598+ ASSERT_OK (
599+ CreateOutboundReplicationGroupSync (kReplicationGroupId , {namespace_id_, namespace_id_2}));
597600 {
598601 auto group_info = ASSERT_RESULT (
599602 XClusterClient ().GetXClusterOutboundReplicationGroupInfo (kReplicationGroupId ));
@@ -606,10 +609,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, TestListAPIs) {
606609
607610 // Replication group 2 with one namespace.
608611 const xcluster::ReplicationGroupId replication_group2 (" rg2" );
609- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
610- replication_group2, {namespace_id_}, UseAutomaticMode ()));
611- ASSERT_OK (GetXClusterStreams (replication_group2, namespace_id_));
612- // Wait for checkpointing to complete.
612+ ASSERT_OK (CreateOutboundReplicationGroupSync (replication_group2, {namespace_id_}));
613613 {
614614 auto group_info =
615615 ASSERT_RESULT (XClusterClient ().GetXClusterOutboundReplicationGroupInfo (replication_group2));
@@ -679,8 +679,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, TestListAPIs) {
679679// Make sure we cleanup the streams of the failed table create.
680680TEST_P (XClusterOutboundReplicationGroupParameterized, CleanupStreamsOfFailedTableCreate) {
681681 auto table_id_1 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName1 ));
682- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
683- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
682+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
684683 int expected_stream_count = 1 + OverheadStreamsCount ();
685684
686685 auto check_streams = [&]() -> Status {
@@ -719,11 +718,7 @@ TEST_P(XClusterOutboundReplicationGroupParameterized, CleanupStreamsOfFailedTabl
719718TEST_P (XClusterOutboundReplicationGroupParameterized, TestGetStreamByTableId) {
720719 auto table_id_1 = ASSERT_RESULT (CreateYsqlTable (kNamespaceName , kTableName1 ));
721720
722- ASSERT_OK (XClusterClient ().CreateOutboundReplicationGroup (
723- kReplicationGroupId , {namespace_id_}, UseAutomaticMode ()));
724-
725- // Wait for the namespace to be ready.
726- ASSERT_OK (GetXClusterStreams (kReplicationGroupId , namespace_id_));
721+ ASSERT_OK (CreateOutboundReplicationGroupSync ());
727722
728723 // Delete the table to put it into HIDDEN state.
729724 ASSERT_OK (DropYsqlTable (&producer_cluster_, kNamespaceName , kPgSchemaName , kTableName1 ));
0 commit comments