1313import org .elasticsearch .ExceptionsHelper ;
1414import org .elasticsearch .action .ActionListener ;
1515import org .elasticsearch .action .admin .cluster .state .ClusterStateRequest ;
16+ import org .elasticsearch .action .admin .cluster .state .ClusterStateResponse ;
1617import org .elasticsearch .client .Client ;
1718import org .elasticsearch .cluster .ClusterChangedEvent ;
1819import org .elasticsearch .cluster .ClusterState ;
2425import org .elasticsearch .cluster .service .ClusterService ;
2526import org .elasticsearch .common .collect .CopyOnWriteHashMap ;
2627import org .elasticsearch .common .collect .Tuple ;
27- import org .elasticsearch .common .unit .TimeValue ;
2828import org .elasticsearch .common .util .concurrent .AtomicArray ;
2929import org .elasticsearch .common .util .concurrent .CountDown ;
3030import org .elasticsearch .index .Index ;
3131import org .elasticsearch .index .IndexSettings ;
3232import org .elasticsearch .license .LicenseUtils ;
33- import org .elasticsearch .threadpool .ThreadPool ;
3433import org .elasticsearch .xpack .ccr .CcrLicenseChecker ;
3534import org .elasticsearch .xpack .core .ccr .AutoFollowMetadata ;
3635import org .elasticsearch .xpack .core .ccr .AutoFollowMetadata .AutoFollowPattern ;
@@ -64,7 +63,6 @@ public class AutoFollowCoordinator implements ClusterStateListener {
6463 private static final int MAX_AUTO_FOLLOW_ERRORS = 256 ;
6564
6665 private final Client client ;
67- private final ThreadPool threadPool ;
6866 private final ClusterService clusterService ;
6967 private final CcrLicenseChecker ccrLicenseChecker ;
7068
@@ -78,11 +76,9 @@ public class AutoFollowCoordinator implements ClusterStateListener {
7876
7977 public AutoFollowCoordinator (
8078 Client client ,
81- ThreadPool threadPool ,
8279 ClusterService clusterService ,
8380 CcrLicenseChecker ccrLicenseChecker ) {
8481 this .client = client ;
85- this .threadPool = threadPool ;
8682 this .clusterService = clusterService ;
8783 this .ccrLicenseChecker = Objects .requireNonNull (ccrLicenseChecker , "ccrLicenseChecker" );
8884 clusterService .addListener (this );
@@ -148,22 +144,24 @@ void updateAutoFollowers(ClusterState followerClusterState) {
148144
149145 Map <String , AutoFollower > newAutoFollowers = new HashMap <>(newRemoteClusters .size ());
150146 for (String remoteCluster : newRemoteClusters ) {
151- AutoFollower autoFollower = new AutoFollower (remoteCluster , threadPool , this ::updateStats , clusterService ::state ) {
147+ AutoFollower autoFollower = new AutoFollower (remoteCluster , this ::updateStats , clusterService ::state ) {
152148
153149 @ Override
154150 void getRemoteClusterState (final String remoteCluster ,
155- final BiConsumer <ClusterState , Exception > handler ) {
151+ final long metadataVersion ,
152+ final BiConsumer <ClusterStateResponse , Exception > handler ) {
156153 final ClusterStateRequest request = new ClusterStateRequest ();
157154 request .clear ();
158155 request .metaData (true );
159156 request .routingTable (true );
157+ request .waitForMetaDataVersion (metadataVersion );
160158 // TODO: set non-compliant status on auto-follow coordination that can be viewed via a stats API
161159 ccrLicenseChecker .checkRemoteClusterLicenseAndFetchClusterState (
162160 client ,
163161 remoteCluster ,
164162 request ,
165163 e -> handler .accept (null , e ),
166- remoteClusterState -> handler .accept (remoteClusterState , null ));
164+ remoteClusterStateResponse -> handler .accept (remoteClusterStateResponse , null ));
167165 }
168166
169167 @ Override
@@ -237,19 +235,17 @@ public void clusterChanged(ClusterChangedEvent event) {
237235 abstract static class AutoFollower {
238236
239237 private final String remoteCluster ;
240- private final ThreadPool threadPool ;
241238 private final Consumer <List <AutoFollowResult >> statsUpdater ;
242239 private final Supplier <ClusterState > followerClusterStateSupplier ;
243240
241+ private volatile long metadataVersion = 0 ;
244242 private volatile CountDown autoFollowPatternsCountDown ;
245243 private volatile AtomicArray <AutoFollowResult > autoFollowResults ;
246244
247245 AutoFollower (final String remoteCluster ,
248- final ThreadPool threadPool ,
249246 final Consumer <List <AutoFollowResult >> statsUpdater ,
250247 final Supplier <ClusterState > followerClusterStateSupplier ) {
251248 this .remoteCluster = remoteCluster ;
252- this .threadPool = threadPool ;
253249 this .statsUpdater = statsUpdater ;
254250 this .followerClusterStateSupplier = followerClusterStateSupplier ;
255251 }
@@ -274,9 +270,15 @@ void start() {
274270 this .autoFollowPatternsCountDown = new CountDown (patterns .size ());
275271 this .autoFollowResults = new AtomicArray <>(patterns .size ());
276272
277- getRemoteClusterState (remoteCluster , ( remoteClusterState , remoteError ) -> {
278- if (remoteClusterState != null ) {
273+ getRemoteClusterState (remoteCluster , metadataVersion + 1 , ( remoteClusterStateResponse , remoteError ) -> {
274+ if (remoteClusterStateResponse != null ) {
279275 assert remoteError == null ;
276+ if (remoteClusterStateResponse .isWaitForTimedOut ()) {
277+ start ();
278+ return ;
279+ }
280+ ClusterState remoteClusterState = remoteClusterStateResponse .getState ();
281+ metadataVersion = remoteClusterState .metaData ().version ();
280282 autoFollowIndices (autoFollowMetadata , clusterState , remoteClusterState , patterns );
281283 } else {
282284 assert remoteError != null ;
@@ -400,8 +402,7 @@ private void finalise(int slot, AutoFollowResult result) {
400402 autoFollowResults .set (slot , result );
401403 if (autoFollowPatternsCountDown .countDown ()) {
402404 statsUpdater .accept (autoFollowResults .asList ());
403- // TODO: Remove scheduling here with using cluster state API's waitForMetadataVersion:
404- threadPool .schedule (TimeValue .timeValueMillis (2500 ), ThreadPool .Names .GENERIC , this ::start );
405+ start ();
405406 }
406407 }
407408
@@ -520,13 +521,15 @@ static Function<ClusterState, ClusterState> cleanFollowedRemoteIndices(
520521 }
521522
522523 /**
523- * Fetch the cluster state from the leader with the specified cluster alias
524+ * Fetch a remote cluster state from with the specified cluster alias
524525 * @param remoteCluster the name of the leader cluster
526+ * @param metadataVersion the last seen metadata version
525527 * @param handler the callback to invoke
526528 */
527529 abstract void getRemoteClusterState (
528530 String remoteCluster ,
529- BiConsumer <ClusterState , Exception > handler
531+ long metadataVersion ,
532+ BiConsumer <ClusterStateResponse , Exception > handler
530533 );
531534
532535 abstract void createAndFollow (
0 commit comments