@@ -252,6 +252,91 @@ public void testExceptionOnStart() {
252
252
assertThat (lifeCycleService .getState ().get (), equalTo (WatcherState .STARTED ));
253
253
}
254
254
255
+ public void testReloadWithIdenticalRoutingTable () {
256
+ /*
257
+ * This tests that the identical routing table causes reload only once.
258
+ */
259
+ startWatcher ();
260
+
261
+ ClusterChangedEvent [] events = masterChangeScenario ();
262
+ assertThat (events [1 ].previousState (), equalTo (events [0 ].state ()));
263
+ assertFalse (events [1 ].routingTableChanged ());
264
+
265
+ for (ClusterChangedEvent event : events ) {
266
+ when (watcherService .validate (event .state ())).thenReturn (true );
267
+ lifeCycleService .clusterChanged (event );
268
+ }
269
+ // reload should occur on the first event
270
+ verify (watcherService ).reload (eq (events [0 ].state ()), anyString (), any ());
271
+ // but it shouldn't on the second event unless routing table changes
272
+ verify (watcherService , never ()).reload (eq (events [1 ].state ()), anyString (), any ());
273
+ }
274
+
275
+ public void testReloadWithIdenticalRoutingTableAfterException () {
276
+ /*
277
+ * This tests that even the identical routing table causes reload again if some exception (for example a timeout while loading
278
+ * watches) interrupted the previous one.
279
+ */
280
+ startWatcher ();
281
+
282
+ ClusterChangedEvent [] events = masterChangeScenario ();
283
+ assertThat (events [1 ].previousState (), equalTo (events [0 ].state ()));
284
+ assertFalse (events [1 ].routingTableChanged ());
285
+
286
+ // simulate exception on the first event
287
+ doAnswer (invocation -> {
288
+ Consumer <Exception > exceptionConsumer = invocation .getArgument (2 );
289
+ exceptionConsumer .accept (new ElasticsearchTimeoutException (new TimeoutException ("Artificial timeout" )));
290
+ return null ;
291
+ }).when (watcherService ).reload (eq (events [0 ].state ()), anyString (), any ());
292
+
293
+ for (ClusterChangedEvent event : events ) {
294
+ when (watcherService .validate (event .state ())).thenReturn (true );
295
+ lifeCycleService .clusterChanged (event );
296
+ }
297
+ // reload should occur on the first event but it fails
298
+ verify (watcherService ).reload (eq (events [0 ].state ()), anyString (), any ());
299
+ // reload should occur again on the second event because the previous one failed
300
+ verify (watcherService ).reload (eq (events [1 ].state ()), anyString (), any ());
301
+ }
302
+
303
+ private ClusterChangedEvent [] masterChangeScenario () {
304
+ DiscoveryNodes nodes = new DiscoveryNodes .Builder ().localNodeId ("node_1" ).add (newNode ("node_1" )).add (newNode ("node_2" )).build ();
305
+
306
+ Index index = new Index (Watch .INDEX , "uuid" );
307
+ IndexRoutingTable .Builder indexRoutingTableBuilder = IndexRoutingTable .builder (index );
308
+ indexRoutingTableBuilder .addShard (
309
+ TestShardRouting .newShardRouting (new ShardId (index , 0 ), "node_1" , true , ShardRoutingState .STARTED )
310
+ );
311
+ RoutingTable routingTable = RoutingTable .builder ().add (indexRoutingTableBuilder .build ()).build ();
312
+
313
+ IndexMetadata .Builder indexMetadataBuilder = IndexMetadata .builder (Watch .INDEX )
314
+ .settings (settings (Version .CURRENT ).put (IndexMetadata .INDEX_FORMAT_SETTING .getKey (), 6 )) // the internal index format,
315
+ // required
316
+ .numberOfShards (1 )
317
+ .numberOfReplicas (0 );
318
+ Metadata metadata = Metadata .builder ()
319
+ .put (IndexTemplateMetadata .builder (HISTORY_TEMPLATE_NAME ).patterns (randomIndexPatterns ()))
320
+ .put (indexMetadataBuilder )
321
+ .build ();
322
+
323
+ ClusterState emptyState = ClusterState .builder (new ClusterName ("my-cluster" )).nodes (nodes ).metadata (metadata ).build ();
324
+ ClusterState stateWithMasterNode1 = ClusterState .builder (new ClusterName ("my-cluster" ))
325
+ .nodes (DiscoveryNodes .builder (nodes ).masterNodeId ("node_1" ))
326
+ .metadata (metadata )
327
+ .routingTable (routingTable )
328
+ .build ();
329
+ ClusterState stateWithMasterNode2 = ClusterState .builder (new ClusterName ("my-cluster" ))
330
+ .nodes (DiscoveryNodes .builder (nodes ).masterNodeId ("node_2" ))
331
+ .metadata (metadata )
332
+ .routingTable (routingTable )
333
+ .build ();
334
+
335
+ return new ClusterChangedEvent [] {
336
+ new ClusterChangedEvent ("any" , stateWithMasterNode1 , emptyState ),
337
+ new ClusterChangedEvent ("any" , stateWithMasterNode2 , stateWithMasterNode1 ) };
338
+ }
339
+
255
340
public void testNoLocalShards () {
256
341
Index watchIndex = new Index (Watch .INDEX , "foo" );
257
342
ShardId shardId = new ShardId (watchIndex , 0 );
@@ -301,7 +386,7 @@ public void testNoLocalShards() {
301
386
when (watcherService .validate (eq (clusterStateWithLocalShards ))).thenReturn (true );
302
387
when (watcherService .validate (eq (clusterStateWithoutLocalShards ))).thenReturn (false );
303
388
lifeCycleService .clusterChanged (new ClusterChangedEvent ("any" , clusterStateWithLocalShards , clusterStateWithoutLocalShards ));
304
- verify (watcherService , times (1 )).reload (eq (clusterStateWithLocalShards ), eq ("new local watcher shard allocation ids" ));
389
+ verify (watcherService , times (1 )).reload (eq (clusterStateWithLocalShards ), eq ("new local watcher shard allocation ids" ), any () );
305
390
verify (watcherService , times (1 )).validate (eq (clusterStateWithLocalShards ));
306
391
verifyNoMoreInteractions (watcherService );
307
392
@@ -386,12 +471,12 @@ public void testReplicaWasAddedOrRemoved() {
386
471
387
472
when (watcherService .validate (eq (firstEvent .state ()))).thenReturn (true );
388
473
lifeCycleService .clusterChanged (firstEvent );
389
- verify (watcherService ).reload (eq (firstEvent .state ()), anyString ());
474
+ verify (watcherService ).reload (eq (firstEvent .state ()), anyString (), any () );
390
475
391
476
reset (watcherService );
392
477
when (watcherService .validate (eq (secondEvent .state ()))).thenReturn (true );
393
478
lifeCycleService .clusterChanged (secondEvent );
394
- verify (watcherService ).reload (eq (secondEvent .state ()), anyString ());
479
+ verify (watcherService ).reload (eq (secondEvent .state ()), anyString (), any () );
395
480
}
396
481
397
482
// make sure that cluster state changes can be processed on nodes that do not hold data
@@ -457,7 +542,7 @@ public void testNonDataNode() {
457
542
458
543
lifeCycleService .clusterChanged (new ClusterChangedEvent ("any" , currentState , previousState ));
459
544
verify (watcherService , times (0 )).pauseExecution (any ());
460
- verify (watcherService , times (0 )).reload (any (), any ());
545
+ verify (watcherService , times (0 )).reload (any (), any (), any () );
461
546
}
462
547
463
548
public void testThatMissingWatcherIndexMetadataOnlyResetsOnce () {
@@ -490,7 +575,7 @@ public void testThatMissingWatcherIndexMetadataOnlyResetsOnce() {
490
575
491
576
// first add the shard allocation ids, by going from empty cs to CS with watcher index
492
577
lifeCycleService .clusterChanged (new ClusterChangedEvent ("any" , clusterStateWithWatcherIndex , clusterStateWithoutWatcherIndex ));
493
- verify (watcherService ).reload (eq (clusterStateWithWatcherIndex ), anyString ());
578
+ verify (watcherService ).reload (eq (clusterStateWithWatcherIndex ), anyString (), any () );
494
579
495
580
// now remove watches index, and ensure that pausing is only called once, no matter how often called (i.e. each CS update)
496
581
lifeCycleService .clusterChanged (new ClusterChangedEvent ("any" , clusterStateWithoutWatcherIndex , clusterStateWithWatcherIndex ));
@@ -629,7 +714,7 @@ public void testWatcherReloadsOnNodeOutageWithWatcherShard() {
629
714
when (watcherService .validate (any ())).thenReturn (true );
630
715
ClusterChangedEvent event = new ClusterChangedEvent ("whatever" , currentState , previousState );
631
716
lifeCycleService .clusterChanged (event );
632
- verify (watcherService ).reload (eq (event .state ()), anyString ());
717
+ verify (watcherService ).reload (eq (event .state ()), anyString (), any () );
633
718
}
634
719
635
720
private void startWatcher () {
@@ -658,7 +743,7 @@ private void startWatcher() {
658
743
659
744
lifeCycleService .clusterChanged (new ClusterChangedEvent ("foo" , state , emptyState ));
660
745
assertThat (lifeCycleService .getState ().get (), is (WatcherState .STARTED ));
661
- verify (watcherService , times (1 )).reload (eq (state ), anyString ());
746
+ verify (watcherService , times (1 )).reload (eq (state ), anyString (), any () );
662
747
assertThat (lifeCycleService .shardRoutings (), hasSize (1 ));
663
748
664
749
// reset the mock, the user has to mock everything themselves again
0 commit comments