|
95 | 95 | import static org.elasticsearch.cluster.coordination.LeaderChecker.LEADER_CHECK_RETRY_COUNT_SETTING;
|
96 | 96 | import static org.elasticsearch.cluster.coordination.LeaderChecker.LEADER_CHECK_TIMEOUT_SETTING;
|
97 | 97 | import static org.elasticsearch.cluster.coordination.Reconfigurator.CLUSTER_AUTO_SHRINK_VOTING_CONFIGURATION;
|
| 98 | +import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_ID; |
98 | 99 | import static org.elasticsearch.discovery.PeerFinder.DISCOVERY_FIND_PEERS_INTERVAL_SETTING;
|
99 | 100 | import static org.elasticsearch.node.Node.NODE_NAME_SETTING;
|
100 | 101 | import static org.elasticsearch.transport.TransportService.HANDSHAKE_ACTION_NAME;
|
|
110 | 111 | import static org.hamcrest.Matchers.lessThan;
|
111 | 112 | import static org.hamcrest.Matchers.lessThanOrEqualTo;
|
112 | 113 | import static org.hamcrest.Matchers.not;
|
| 114 | +import static org.hamcrest.Matchers.nullValue; |
113 | 115 | import static org.hamcrest.Matchers.sameInstance;
|
114 | 116 | import static org.hamcrest.Matchers.startsWith;
|
115 | 117 |
|
@@ -887,6 +889,31 @@ public void testIncompatibleDiffResendsFullState() {
|
887 | 889 | postPublishStats.getIncompatibleClusterStateDiffReceivedCount());
|
888 | 890 | }
|
889 | 891 |
|
| 892 | + /** |
| 893 | + * Simulates a situation where a follower becomes disconnected from the leader, but only for such a short time where |
| 894 | + * it becomes candidate and puts up a NO_MASTER_BLOCK, but then receives a follower check from the leader. If the leader |
| 895 | + * does not notice the node disconnecting, it is important for the node not to be turned back into a follower but try |
| 896 | + * and join the leader again. |
| 897 | + */ |
| 898 | + public void testStayCandidateAfterReceivingFollowerCheckFromKnownMaster() { |
| 899 | + final Cluster cluster = new Cluster(2, false); |
| 900 | + cluster.runRandomly(); |
| 901 | + cluster.stabilise(); |
| 902 | + |
| 903 | + final ClusterNode leader = cluster.getAnyLeader(); |
| 904 | + final ClusterNode nonLeader = cluster.getAnyNodeExcept(leader); |
| 905 | + onNode(nonLeader.getLocalNode(), () -> { |
| 906 | + logger.debug("forcing {} to become candidate", nonLeader.getId()); |
| 907 | + synchronized (nonLeader.coordinator.mutex) { |
| 908 | + nonLeader.coordinator.becomeCandidate("forced"); |
| 909 | + } |
| 910 | + logger.debug("simulate follower check coming through from {} to {}", leader.getId(), nonLeader.getId()); |
| 911 | + nonLeader.coordinator.onFollowerCheckRequest(new FollowersChecker.FollowerCheckRequest(leader.coordinator.getCurrentTerm(), |
| 912 | + leader.getLocalNode())); |
| 913 | + }).run(); |
| 914 | + cluster.stabilise(); |
| 915 | + } |
| 916 | + |
890 | 917 | private static long defaultMillis(Setting<TimeValue> setting) {
|
891 | 918 | return setting.get(Settings.EMPTY).millis() + Cluster.DEFAULT_DELAY_VARIABILITY;
|
892 | 919 | }
|
@@ -1176,8 +1203,15 @@ void stabilise(long stabilisationDurationMillis) {
|
1176 | 1203 | assertTrue(nodeId + " is in the latest applied state on " + leaderId,
|
1177 | 1204 | leader.getLastAppliedClusterState().getNodes().nodeExists(nodeId));
|
1178 | 1205 | assertTrue(nodeId + " has been bootstrapped", clusterNode.coordinator.isInitialConfigurationSet());
|
| 1206 | + assertThat(nodeId + " has correct master", clusterNode.getLastAppliedClusterState().nodes().getMasterNode(), |
| 1207 | + equalTo(leader.getLocalNode())); |
| 1208 | + assertThat(nodeId + " has no NO_MASTER_BLOCK", |
| 1209 | + clusterNode.getLastAppliedClusterState().blocks().hasGlobalBlock(NO_MASTER_BLOCK_ID), equalTo(false)); |
1179 | 1210 | } else {
|
1180 | 1211 | assertThat(nodeId + " is not following " + leaderId, clusterNode.coordinator.getMode(), is(CANDIDATE));
|
| 1212 | + assertThat(nodeId + " has no master", clusterNode.getLastAppliedClusterState().nodes().getMasterNode(), nullValue()); |
| 1213 | + assertThat(nodeId + " has NO_MASTER_BLOCK", |
| 1214 | + clusterNode.getLastAppliedClusterState().blocks().hasGlobalBlock(NO_MASTER_BLOCK_ID), equalTo(true)); |
1181 | 1215 | assertFalse(nodeId + " is not in the applied state on " + leaderId,
|
1182 | 1216 | leader.getLastAppliedClusterState().getNodes().nodeExists(nodeId));
|
1183 | 1217 | }
|
|
0 commit comments