@@ -254,9 +254,12 @@ public void testReplicaWasAddedOrRemoved() {
254254 .add (newNode ("node_2" ))
255255 .build ();
256256
257+ ShardRouting firstShardOnSecondNode = TestShardRouting .newShardRouting (shardId , "node_2" , true , STARTED );
258+ ShardRouting secondShardOnFirstNode = TestShardRouting .newShardRouting (secondShardId , "node_1" , true , STARTED );
259+
257260 IndexRoutingTable previousWatchRoutingTable = IndexRoutingTable .builder (watchIndex )
258- .addShard (TestShardRouting . newShardRouting ( secondShardId , "node_1" , true , STARTED ) )
259- .addShard (TestShardRouting . newShardRouting ( shardId , "node_2" , true , STARTED ) )
261+ .addShard (secondShardOnFirstNode )
262+ .addShard (firstShardOnSecondNode )
260263 .build ();
261264
262265 IndexMetaData indexMetaData = IndexMetaData .builder (Watch .INDEX )
@@ -273,10 +276,19 @@ public void testReplicaWasAddedOrRemoved() {
273276 .metaData (MetaData .builder ().put (indexMetaData , false ))
274277 .build ();
275278
279+ // add a replica in the local node
280+ boolean addShardOnLocalNode = randomBoolean ();
281+ final ShardRouting addedShardRouting ;
282+ if (addShardOnLocalNode ) {
283+ addedShardRouting = TestShardRouting .newShardRouting (shardId , "node_1" , false , STARTED );
284+ } else {
285+ addedShardRouting = TestShardRouting .newShardRouting (secondShardId , "node_2" , false , STARTED );
286+ }
287+
276288 IndexRoutingTable currentWatchRoutingTable = IndexRoutingTable .builder (watchIndex )
277- .addShard (TestShardRouting . newShardRouting ( shardId , "node_1" , false , STARTED ) )
278- .addShard (TestShardRouting . newShardRouting ( secondShardId , "node_1" , true , STARTED ) )
279- .addShard (TestShardRouting . newShardRouting ( shardId , "node_2" , true , STARTED ) )
289+ .addShard (secondShardOnFirstNode )
290+ .addShard (firstShardOnSecondNode )
291+ .addShard (addedShardRouting )
280292 .build ();
281293
282294 ClusterState stateWithReplicaAdded = ClusterState .builder (new ClusterName ("my-cluster" ))
@@ -477,7 +489,67 @@ public void testDataNodeWithoutDataCanStart() {
477489 assertThat (lifeCycleService .getState (), is (WatcherState .STARTED ));
478490 }
479491
480- private ClusterState startWatcher () {
492+ // this emulates a node outage somewhere in the cluster that carried a watcher shard
493+ // the number of shards remains the same, but we need to ensure that watcher properly reloads
494+ // previously we only checked the local shard allocations, but we also need to check if shards in the cluster have changed
495+ public void testWatcherReloadsOnNodeOutageWithWatcherShard () {
496+ Index watchIndex = new Index (Watch .INDEX , "foo" );
497+ ShardId shardId = new ShardId (watchIndex , 0 );
498+ String localNodeId = randomFrom ("node_1" , "node_2" );
499+ String outageNodeId = localNodeId .equals ("node_1" ) ? "node_2" : "node_1" ;
500+ DiscoveryNodes previousDiscoveryNodes = new DiscoveryNodes .Builder ().masterNodeId (localNodeId ).localNodeId (localNodeId )
501+ .add (newNode (localNodeId ))
502+ .add (newNode (outageNodeId ))
503+ .build ();
504+
505+ ShardRouting replicaShardRouting = TestShardRouting .newShardRouting (shardId , localNodeId , false , STARTED );
506+ ShardRouting primartShardRouting = TestShardRouting .newShardRouting (shardId , outageNodeId , true , STARTED );
507+ IndexRoutingTable previousWatchRoutingTable = IndexRoutingTable .builder (watchIndex )
508+ .addShard (replicaShardRouting )
509+ .addShard (primartShardRouting )
510+ .build ();
511+
512+ IndexMetaData indexMetaData = IndexMetaData .builder (Watch .INDEX )
513+ .settings (Settings .builder ()
514+ .put (IndexMetaData .SETTING_NUMBER_OF_SHARDS , 1 )
515+ .put (IndexMetaData .SETTING_NUMBER_OF_REPLICAS , 0 )
516+ .put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT )
517+ .put (IndexMetaData .INDEX_FORMAT_SETTING .getKey (), 6 )
518+ ).build ();
519+
520+ ClusterState previousState = ClusterState .builder (new ClusterName ("my-cluster" ))
521+ .nodes (previousDiscoveryNodes )
522+ .routingTable (RoutingTable .builder ().add (previousWatchRoutingTable ).build ())
523+ .metaData (MetaData .builder ().put (indexMetaData , false ))
524+ .build ();
525+
526+ ShardRouting nowPrimaryShardRouting = replicaShardRouting .moveActiveReplicaToPrimary ();
527+ IndexRoutingTable currentWatchRoutingTable = IndexRoutingTable .builder (watchIndex )
528+ .addShard (nowPrimaryShardRouting )
529+ .build ();
530+
531+ DiscoveryNodes currentDiscoveryNodes = new DiscoveryNodes .Builder ().masterNodeId (localNodeId ).localNodeId (localNodeId )
532+ .add (newNode (localNodeId ))
533+ .build ();
534+
535+ ClusterState currentState = ClusterState .builder (new ClusterName ("my-cluster" ))
536+ .nodes (currentDiscoveryNodes )
537+ .routingTable (RoutingTable .builder ().add (currentWatchRoutingTable ).build ())
538+ .metaData (MetaData .builder ().put (indexMetaData , false ))
539+ .build ();
540+
541+ // initialize the previous state, so all the allocation ids are loaded
542+ when (watcherService .validate (anyObject ())).thenReturn (true );
543+ lifeCycleService .clusterChanged (new ClusterChangedEvent ("whatever" , previousState , currentState ));
544+
545+ reset (watcherService );
546+ when (watcherService .validate (anyObject ())).thenReturn (true );
547+ ClusterChangedEvent event = new ClusterChangedEvent ("whatever" , currentState , previousState );
548+ lifeCycleService .clusterChanged (event );
549+ verify (watcherService ).reload (eq (event .state ()), anyString ());
550+ }
551+
552+ private void startWatcher () {
481553 Index index = new Index (Watch .INDEX , "uuid" );
482554 IndexRoutingTable .Builder indexRoutingTableBuilder = IndexRoutingTable .builder (index );
483555 indexRoutingTableBuilder .addShard (
@@ -506,12 +578,10 @@ private ClusterState startWatcher() {
506578 lifeCycleService .clusterChanged (new ClusterChangedEvent ("foo" , state , emptyState ));
507579 assertThat (lifeCycleService .getState (), is (WatcherState .STARTED ));
508580 verify (watcherService , times (1 )).reload (eq (state ), anyString ());
509- assertThat (lifeCycleService .allocationIds (), hasSize (1 ));
581+ assertThat (lifeCycleService .shardRoutings (), hasSize (1 ));
510582
511583 // reset the mock, the user has to mock everything themselves again
512584 reset (watcherService );
513-
514- return state ;
515585 }
516586
517587 private List <String > randomIndexPatterns () {
0 commit comments