use of io.atomix.protocols.raft.protocol.KeepAliveRequest in project atomix by atomix.
the class RaftSessionManager method keepAliveSessions.
/**
* Sends a keep-alive request to the cluster.
*/
private synchronized void keepAliveSessions(long lastKeepAliveTime, long sessionTimeout) {
// Filter the list of sessions by timeout.
List<RaftSessionState> needKeepAlive = sessions.values().stream().filter(session -> session.getSessionTimeout() == sessionTimeout).collect(Collectors.toList());
// If no sessions need keep-alives to be sent, skip and reschedule the keep-alive.
if (needKeepAlive.isEmpty()) {
return;
}
// Allocate session IDs, command response sequence numbers, and event index arrays.
long[] sessionIds = new long[needKeepAlive.size()];
long[] commandResponses = new long[needKeepAlive.size()];
long[] eventIndexes = new long[needKeepAlive.size()];
// For each session that needs to be kept alive, populate batch request arrays.
int i = 0;
for (RaftSessionState sessionState : needKeepAlive) {
sessionIds[i] = sessionState.getSessionId().id();
commandResponses[i] = sessionState.getCommandResponse();
eventIndexes[i] = sessionState.getEventIndex();
i++;
}
log.trace("Keeping {} sessions alive", sessionIds.length);
KeepAliveRequest request = KeepAliveRequest.builder().withSessionIds(sessionIds).withCommandSequences(commandResponses).withEventIndexes(eventIndexes).build();
long keepAliveTime = System.currentTimeMillis();
connection.keepAlive(request).whenComplete((response, error) -> {
if (open.get()) {
long delta = System.currentTimeMillis() - keepAliveTime;
if (error == null) {
// If the request was successful, update the address selector and schedule the next keep-alive.
if (response.status() == RaftResponse.Status.OK) {
selectorManager.resetAll(response.leader(), response.members());
// Iterate through sessions and close sessions that weren't kept alive by the request (have already been closed).
Set<Long> keptAliveSessions = Sets.newHashSet(Longs.asList(response.sessionIds()));
for (RaftSessionState session : needKeepAlive) {
if (keptAliveSessions.contains(session.getSessionId().id())) {
session.setState(PrimitiveState.CONNECTED);
} else {
session.setState(PrimitiveState.EXPIRED);
}
}
scheduleKeepAlive(System.currentTimeMillis(), sessionTimeout, delta);
} else // We will continue to retry until the session expiration has passed.
if (System.currentTimeMillis() - lastKeepAliveTime < sessionTimeout) {
selectorManager.resetAll(null, connection.members());
keepAliveSessions(lastKeepAliveTime, sessionTimeout);
} else // If no leader was set, set the session state to unstable and schedule another keep-alive.
{
needKeepAlive.forEach(s -> s.setState(PrimitiveState.SUSPENDED));
selectorManager.resetAll();
scheduleKeepAlive(lastKeepAliveTime, sessionTimeout, delta);
}
} else // again with no delay.
if (System.currentTimeMillis() - lastKeepAliveTime < sessionTimeout && connection.leader() != null) {
selectorManager.resetAll(null, connection.members());
keepAliveSessions(lastKeepAliveTime, sessionTimeout);
} else // If no leader was set, set the session state to unstable and schedule another keep-alive.
{
needKeepAlive.forEach(s -> s.setState(PrimitiveState.SUSPENDED));
selectorManager.resetAll();
scheduleKeepAlive(lastKeepAliveTime, sessionTimeout, delta);
}
}
});
}
Aggregations