/** * Helper method to build local {@link NodeState} based on pings * * @param allServers all servers in the cluster * @param allConnectedNodes all connected nodes in the cluster * @param epoch current epoch * @param sequencerMetrics metrics * @return local node state */ private NodeState getLocalNodeState(Set<String> allServers, Set<String> allConnectedNodes, long epoch, SequencerMetrics sequencerMetrics) { //Get connectivity status for a local node Map<String, ConnectionStatus> connectivity = new HashMap<>(); allServers.forEach(server -> { connectivity.put(server, ConnectionStatus.fromBool(allConnectedNodes.contains(server))); }); NodeConnectivity localConnectivity = NodeConnectivity.connectivity( localEndpoint, ImmutableMap.copyOf(connectivity) ); return NodeState.builder() .connectivity(localConnectivity) .heartbeat(new HeartbeatTimestamp(epoch, heartbeatCounter.incrementHeartbeat())) .sequencerMetrics(sequencerMetrics) .build(); }
@Test public void testDecisionMaker() { NodeConnectivity a = connectivity("a", ImmutableMap.of("a", OK, "b", OK, "c", OK)); NodeConnectivity b = connectivity("b", ImmutableMap.of("a", FAILED, "b", OK, "c", OK)); NodeConnectivity c = connectivity("c", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)); ClusterGraph graph = cluster("a", a, b, c); Optional<NodeRank> decisionMaker = graph.toSymmetric().getDecisionMaker(); assertTrue(decisionMaker.isPresent()); assertEquals(decisionMaker.get(), new NodeRank("a", 2)); }
@Test public void testFailedNode() { NodeConnectivity a = connectivity("a", ImmutableMap.of("a", OK, "b", OK, "c", OK)); NodeConnectivity b = connectivity("b", ImmutableMap.of("a", FAILED, "b", OK, "c", OK)); NodeConnectivity c = connectivity("c", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)); ClusterGraph graph = cluster("a", a, b, c); Optional<NodeRank> failedNode = graph.toSymmetric().findFailedNode(); assertTrue(failedNode.isPresent()); assertEquals(failedNode.get(), new NodeRank("b", 1)); }
@Test public void testFindFullyConnectedResponsiveNodes() { ClusterGraph graph = cluster( "a", connectivity("a", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)), unavailable("b"), connectivity("c", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)) ); graph = graph.toSymmetric(); Optional<NodeRank> responsiveNode = graph.findFullyConnectedNode("c", Collections.singletonList("b")); assertTrue(responsiveNode.isPresent()); assertEquals(new NodeRank("c", 2), responsiveNode.get()); responsiveNode = graph.findFullyConnectedNode("c", Collections.singletonList("c")); assertTrue(responsiveNode.isPresent()); assertEquals("c", responsiveNode.get().getEndpoint()); assertEquals(2, responsiveNode.get().getNumConnections()); graph = cluster( "a", connectivity("a", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)), connectivity("b", ImmutableMap.of("a", FAILED, "b", OK, "c", FAILED)), connectivity("c", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)) ); graph = graph.toSymmetric(); responsiveNode = graph.findFullyConnectedNode("c", Collections.singletonList("b")); assertTrue(responsiveNode.isPresent()); assertEquals(new NodeRank("c", 2), responsiveNode.get()); }
@Test public void testToSymmetricForTwoNodes() { NodeConnectivity a = connectivity("a", ImmutableMap.of("a", OK, "b", FAILED)); NodeConnectivity b = connectivity("b", ImmutableMap.of("a", OK, "b", OK)); ClusterGraph graph = cluster("a", a, b); ClusterGraph symmetric = graph.toSymmetric(); assertEquals(FAILED, graph.getNodeConnectivity("a").getConnectionStatus("b")); assertEquals(OK, graph.getNodeConnectivity("b").getConnectionStatus("a")); assertEquals(FAILED, symmetric.getNodeConnectivity("a").getConnectionStatus("b")); assertEquals(FAILED, symmetric.getNodeConnectivity("b").getConnectionStatus("a")); }
@Test public void testToSymmetricForThreeNodes() { NodeConnectivity a = connectivity("a", ImmutableMap.of("a", OK, "b", FAILED, "c", FAILED)); NodeConnectivity b = connectivity("b", ImmutableMap.of("a", OK, "b", OK, "c", OK)); NodeConnectivity c = connectivity("c", ImmutableMap.of("a", OK, "b", FAILED, "c", OK)); ClusterGraph symmetric = cluster("a", a, b, c).toSymmetric(); assertEquals(FAILED, symmetric.getNodeConnectivity("b").getConnectionStatus("a")); assertEquals(FAILED, symmetric.getNodeConnectivity("c").getConnectionStatus("a")); symmetric = cluster("b", a, b, c).toSymmetric(); assertEquals(FAILED, symmetric.getNodeConnectivity("b").getConnectionStatus("a")); assertEquals(FAILED, symmetric.getNodeConnectivity("c").getConnectionStatus("a")); symmetric = cluster("c", a, b, c).toSymmetric(); assertEquals(FAILED, symmetric.getNodeConnectivity("b").getConnectionStatus("a")); assertEquals(FAILED, symmetric.getNodeConnectivity("c").getConnectionStatus("a")); }
@Test public void testToSymmetricForThreeNodesWithUnavailableNodeB() { NodeConnectivity a = connectivity("a", ImmutableMap.of("a", OK, "b", FAILED, "c", FAILED)); NodeConnectivity b = unavailable("b"); NodeConnectivity c = connectivity("c", ImmutableMap.of("a", OK, "b", OK, "c", OK)); ClusterGraph graph = cluster("a", a, b, c); ClusterGraph symmetric = graph.toSymmetric(); NodeConnectivity symmetricNodeA = symmetric.getNodeConnectivity("a"); assertEquals(OK, symmetricNodeA.getConnectionStatus("a")); assertEquals(FAILED, symmetricNodeA.getConnectionStatus("b")); assertEquals(FAILED, symmetricNodeA.getConnectionStatus("c")); assertThatThrownBy(() -> symmetric.getNodeConnectivity("b").getConnectionStatus("a")) .isInstanceOf(IllegalStateException.class); assertEquals(FAILED, symmetric.getNodeConnectivity("c").getConnectionStatus("a")); assertEquals(OK, symmetric.getNodeConnectivity("c").getConnectionStatus("b")); assertEquals(OK, symmetric.getNodeConnectivity("c").getConnectionStatus("c")); }
@Test public void testTransformation() { NodeState a = NodeState.builder() .sequencerMetrics(SequencerMetrics.READY) .heartbeat(new HeartbeatTimestamp(0, 0)) .connectivity(connectivity("a", ImmutableMap.of("a", OK, "b", OK, "c", FAILED))) .build(); NodeState b = NodeState.builder() .sequencerMetrics(SequencerMetrics.READY) .heartbeat(new HeartbeatTimestamp(0, 0)) .connectivity(connectivity("b", ImmutableMap.of("a", OK, "b", OK, "c", FAILED))) .build(); NodeState c = unavailableNodeState("c"); ImmutableMap<String, NodeState> nodes = ImmutableMap.of("a", a, "b", b, "c", c); ClusterState clusterState = ClusterState.builder() .nodes(nodes) .build(); ClusterGraph graph = ClusterGraph.toClusterGraph(clusterState, "a"); assertEquals(graph.size(), nodes.size()); }