14
14
import org .elasticsearch .Version ;
15
15
import org .elasticsearch .action .ActionListener ;
16
16
import org .elasticsearch .action .admin .cluster .state .ClusterStateRequest ;
17
+ import org .elasticsearch .action .admin .cluster .state .ClusterStateResponse ;
17
18
import org .elasticsearch .client .Client ;
18
19
import org .elasticsearch .cluster .ClusterChangedEvent ;
19
20
import org .elasticsearch .cluster .ClusterState ;
26
27
import org .elasticsearch .common .collect .CopyOnWriteHashMap ;
27
28
import org .elasticsearch .common .collect .Tuple ;
28
29
import org .elasticsearch .common .settings .Settings ;
29
- import org .elasticsearch .common .unit .TimeValue ;
30
30
import org .elasticsearch .common .util .concurrent .AtomicArray ;
31
31
import org .elasticsearch .common .util .concurrent .CountDown ;
32
32
import org .elasticsearch .index .Index ;
33
33
import org .elasticsearch .index .IndexSettings ;
34
34
import org .elasticsearch .license .LicenseUtils ;
35
- import org .elasticsearch .threadpool .ThreadPool ;
36
35
import org .elasticsearch .xpack .ccr .CcrLicenseChecker ;
37
36
import org .elasticsearch .xpack .core .ccr .AutoFollowMetadata ;
38
37
import org .elasticsearch .xpack .core .ccr .AutoFollowMetadata .AutoFollowPattern ;
@@ -66,7 +65,6 @@ public class AutoFollowCoordinator implements ClusterStateListener {
66
65
private static final int MAX_AUTO_FOLLOW_ERRORS = 256 ;
67
66
68
67
private final Client client ;
69
- private final ThreadPool threadPool ;
70
68
private final ClusterService clusterService ;
71
69
private final CcrLicenseChecker ccrLicenseChecker ;
72
70
@@ -80,11 +78,9 @@ public class AutoFollowCoordinator implements ClusterStateListener {
80
78
81
79
public AutoFollowCoordinator (
82
80
Client client ,
83
- ThreadPool threadPool ,
84
81
ClusterService clusterService ,
85
82
CcrLicenseChecker ccrLicenseChecker ) {
86
83
this .client = client ;
87
- this .threadPool = threadPool ;
88
84
this .clusterService = clusterService ;
89
85
this .ccrLicenseChecker = Objects .requireNonNull (ccrLicenseChecker , "ccrLicenseChecker" );
90
86
clusterService .addListener (this );
@@ -150,22 +146,24 @@ void updateAutoFollowers(ClusterState followerClusterState) {
150
146
151
147
Map <String , AutoFollower > newAutoFollowers = new HashMap <>(newRemoteClusters .size ());
152
148
for (String remoteCluster : newRemoteClusters ) {
153
- AutoFollower autoFollower = new AutoFollower (remoteCluster , threadPool , this ::updateStats , clusterService ::state ) {
149
+ AutoFollower autoFollower = new AutoFollower (remoteCluster , this ::updateStats , clusterService ::state ) {
154
150
155
151
@ Override
156
152
void getRemoteClusterState (final String remoteCluster ,
157
- final BiConsumer <ClusterState , Exception > handler ) {
153
+ final long metadataVersion ,
154
+ final BiConsumer <ClusterStateResponse , Exception > handler ) {
158
155
final ClusterStateRequest request = new ClusterStateRequest ();
159
156
request .clear ();
160
157
request .metaData (true );
161
158
request .routingTable (true );
159
+ request .waitForMetaDataVersion (metadataVersion );
162
160
// TODO: set non-compliant status on auto-follow coordination that can be viewed via a stats API
163
161
ccrLicenseChecker .checkRemoteClusterLicenseAndFetchClusterState (
164
162
client ,
165
163
remoteCluster ,
166
164
request ,
167
165
e -> handler .accept (null , e ),
168
- remoteClusterState -> handler .accept (remoteClusterState , null ));
166
+ remoteClusterStateResponse -> handler .accept (remoteClusterStateResponse , null ));
169
167
}
170
168
171
169
@ Override
@@ -239,19 +237,17 @@ public void clusterChanged(ClusterChangedEvent event) {
239
237
abstract static class AutoFollower {
240
238
241
239
private final String remoteCluster ;
242
- private final ThreadPool threadPool ;
243
240
private final Consumer <List <AutoFollowResult >> statsUpdater ;
244
241
private final Supplier <ClusterState > followerClusterStateSupplier ;
245
242
243
+ private volatile long metadataVersion = 0 ;
246
244
private volatile CountDown autoFollowPatternsCountDown ;
247
245
private volatile AtomicArray <AutoFollowResult > autoFollowResults ;
248
246
249
247
AutoFollower (final String remoteCluster ,
250
- final ThreadPool threadPool ,
251
248
final Consumer <List <AutoFollowResult >> statsUpdater ,
252
249
final Supplier <ClusterState > followerClusterStateSupplier ) {
253
250
this .remoteCluster = remoteCluster ;
254
- this .threadPool = threadPool ;
255
251
this .statsUpdater = statsUpdater ;
256
252
this .followerClusterStateSupplier = followerClusterStateSupplier ;
257
253
}
@@ -276,9 +272,15 @@ void start() {
276
272
this .autoFollowPatternsCountDown = new CountDown (patterns .size ());
277
273
this .autoFollowResults = new AtomicArray <>(patterns .size ());
278
274
279
- getRemoteClusterState (remoteCluster , ( remoteClusterState , remoteError ) -> {
280
- if (remoteClusterState != null ) {
275
+ getRemoteClusterState (remoteCluster , metadataVersion + 1 , ( remoteClusterStateResponse , remoteError ) -> {
276
+ if (remoteClusterStateResponse != null ) {
281
277
assert remoteError == null ;
278
+ if (remoteClusterStateResponse .isWaitForTimedOut ()) {
279
+ start ();
280
+ return ;
281
+ }
282
+ ClusterState remoteClusterState = remoteClusterStateResponse .getState ();
283
+ metadataVersion = remoteClusterState .metaData ().version ();
282
284
autoFollowIndices (autoFollowMetadata , clusterState , remoteClusterState , patterns );
283
285
} else {
284
286
assert remoteError != null ;
@@ -402,8 +404,7 @@ private void finalise(int slot, AutoFollowResult result) {
402
404
autoFollowResults .set (slot , result );
403
405
if (autoFollowPatternsCountDown .countDown ()) {
404
406
statsUpdater .accept (autoFollowResults .asList ());
405
- // TODO: Remove scheduling here with using cluster state API's waitForMetadataVersion:
406
- threadPool .schedule (TimeValue .timeValueMillis (2500 ), ThreadPool .Names .GENERIC , this ::start );
407
+ start ();
407
408
}
408
409
}
409
410
@@ -525,13 +526,15 @@ static Function<ClusterState, ClusterState> cleanFollowedRemoteIndices(
525
526
}
526
527
527
528
/**
528
- * Fetch the cluster state from the leader with the specified cluster alias
529
+ * Fetch a remote cluster state from with the specified cluster alias
529
530
* @param remoteCluster the name of the leader cluster
531
+ * @param metadataVersion the last seen metadata version
530
532
* @param handler the callback to invoke
531
533
*/
532
534
abstract void getRemoteClusterState (
533
535
String remoteCluster ,
534
- BiConsumer <ClusterState , Exception > handler
536
+ long metadataVersion ,
537
+ BiConsumer <ClusterStateResponse , Exception > handler
535
538
);
536
539
537
540
abstract void createAndFollow (
0 commit comments