use of com.sequenceiq.periscope.domain.PeriscopeNode in project cloudbreak by hortonworks.
the class MetricTest method testLeaderElection.
@Test
public void testLeaderElection() {
metricService.submit(MetricType.LEADER, 0);
PeriscopeNode periscopeNode = new PeriscopeNode();
when(periscopeNodeRepository.findById(periscopeNodeConfig.getId())).thenReturn(Optional.of(periscopeNode));
leaderElectionService.leaderElection();
MultiValueMap<String, String> metrics = responseToMap(readMetricsEndpoint());
assertEquals(1.0, Double.parseDouble(metrics.get(toReportedMetricName(PERISCOPE_METRICS_LEADER, false)).get(0)), DELTA);
}
use of com.sequenceiq.periscope.domain.PeriscopeNode in project cloudbreak by hortonworks.
the class HeartbeatService method heartbeat.
private void heartbeat(boolean unLeaderIt) {
if (periscopeNodeConfig.isNodeIdSpecified()) {
String nodeId = periscopeNodeConfig.getId();
try {
retryService.testWith2SecDelayMax5Times(() -> {
try {
PeriscopeNode self = periscopeNodeRepository.findById(nodeId).orElse(new PeriscopeNode(nodeId));
self.setLastUpdated(clock.getCurrentTimeMillis());
if (unLeaderIt) {
self.setLeader(false);
}
periscopeNodeRepository.save(self);
} catch (RuntimeException e) {
LOGGER.error("Failed to update the heartbeat timestamp", e);
throw new ActionFailedException(e.getMessage());
}
return Boolean.TRUE;
});
} catch (ActionFailedException af) {
LOGGER.error("Failed to update the heartbeat timestamp 5 times for node {}: {}", nodeId, af.getMessage());
try {
transactionService.required(() -> {
clusterRepository.deallocateClustersOfNode(nodeId);
return null;
});
} catch (TransactionExecutionException e) {
LOGGER.error("Unable to deallocate clusters", e);
}
}
}
}
use of com.sequenceiq.periscope.domain.PeriscopeNode in project cloudbreak by hortonworks.
the class LeaderElectionService method reallocateOrphanClusters.
private void reallocateOrphanClusters(List<PeriscopeNode> activeNodes) {
if (activeNodes.stream().noneMatch(n -> n.isLeader() && n.getUuid().equals(periscopeNodeConfig.getId()))) {
Optional<PeriscopeNode> leader = activeNodes.stream().filter(PeriscopeNode::isLeader).findFirst();
LOGGER.info("Leader is {}, let's drop leader scope", leader.isPresent() ? leader.get().getUuid() : "-");
resetTimer();
return;
}
List<String> nodeIds = activeNodes.stream().map(PeriscopeNode::getUuid).collect(Collectors.toList());
List<Cluster> orphanClusters = clusterRepository.findAllByPeriscopeNodeIdNotInOrPeriscopeNodeIdIsNull(nodeIds);
if (!orphanClusters.isEmpty()) {
Iterator<PeriscopeNode> iterator = activeNodes.iterator();
for (Cluster cluster : orphanClusters) {
if (!iterator.hasNext()) {
iterator = activeNodes.iterator();
}
if (isExecutionOfMissedTimeBasedAlertsNeeded(cluster)) {
LOGGER.info("Executing missed alerts on cluster {}", cluster.getId());
executeMissedTimeBasedAlerts(cluster);
}
cluster.setPeriscopeNodeId(iterator.next().getUuid());
LOGGER.info("Allocationg cluster {} to node {}", cluster.getId(), cluster.getPeriscopeNodeId());
}
clusterRepository.saveAll(orphanClusters);
}
}
use of com.sequenceiq.periscope.domain.PeriscopeNode in project cloudbreak by hortonworks.
the class LeaderElectionService method leaderElection.
@Scheduled(initialDelay = 35000L, fixedDelay = 30000L)
public void leaderElection() {
if (periscopeNodeConfig.isNodeIdSpecified()) {
long leaders = periscopeNodeRepository.countByLeaderIsTrueAndLastUpdatedIsGreaterThan(clock.getCurrentTimeMillis() - heartbeatThresholdRate);
if (leaders == 0L) {
metricService.submit(MetricType.LEADER, 0);
LOGGER.info("There is no active leader available");
resetTimer();
try {
transactionService.required(() -> {
periscopeNodeRepository.deallocateLeader();
PeriscopeNode me = periscopeNodeRepository.findById(periscopeNodeConfig.getId()).orElseThrow(notFound("Periscope node", periscopeNodeConfig.getId()));
me.setLeader(true);
periscopeNodeRepository.save(me);
return null;
});
} catch (TransactionExecutionException e) {
LOGGER.error("Failed to select node as leader, something went wrong. Message: {}", e.getMessage());
return;
}
metricService.submit(MetricType.LEADER, 1);
LOGGER.info("Selected {} as leader", periscopeNodeConfig.getId());
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
long limit = clock.getCurrentTimeMillis() - heartbeatThresholdRate;
List<PeriscopeNode> activeNodes = periscopeNodeRepository.findAllByLastUpdatedIsGreaterThan(limit);
if (!activeNodes.isEmpty()) {
reallocateOrphanClusters(activeNodes);
cleanupInactiveNodesByActiveNodes(activeNodes);
}
} catch (RuntimeException e) {
LOGGER.error("Error happend during fetching cluster allocating them to nodes", e);
}
}
}, LEADER_TASK_DELAY, STACK_COLLECTOR_PERIOD);
}
}
}
use of com.sequenceiq.periscope.domain.PeriscopeNode in project cloudbreak by hortonworks.
the class LeaderElectionServiceTest method testReallocateOrphanClustersIsLeader.
@Test
public void testReallocateOrphanClustersIsLeader() throws TransactionExecutionException {
when(periscopeNodeRepository.countByLeaderIsTrueAndLastUpdatedIsGreaterThan(anyLong())).thenReturn(0L);
SpyTimer spyTimer = new SpyTimer();
when(timerFactory.get()).thenReturn(spyTimer);
PeriscopeNode leader = new PeriscopeNode("nodeid");
leader.setLeader(true);
when(periscopeNodeRepository.findAllByLastUpdatedIsGreaterThan(anyLong())).thenReturn(Collections.singletonList(leader));
when(clusterRepository.findAllByPeriscopeNodeIdNotInOrPeriscopeNodeIdIsNull(any())).thenReturn(Collections.singletonList(new Cluster()));
underTest.leaderElection();
spyTimer.lastTask.run();
verify(transactionService, times(2)).required(any(Supplier.class));
verify(clusterRepository, times(1)).findAllByPeriscopeNodeIdNotInOrPeriscopeNodeIdIsNull(any(List.class));
verify(clusterRepository, times(1)).saveAll(any(List.class));
}
Aggregations