+ if (raftActor.getCurrentBehavior() instanceof AbstractLeader leader) {
+ leader.updateMinReplicaCount();
+ }
+
+ return true;
+ }
+
+ private ImmutableList<ServerInfo> newServerInfoList() {
+ final var serverVotingStatusMap = changeVotingStatusContext.getOperation().getServerVotingStatusMap();
+ final var peerInfos = raftContext.getPeers();
+ final var newServerInfoList = ImmutableList.<ServerInfo>builderWithExpectedSize(peerInfos.size() + 1);
+ for (var peerInfo : peerInfos) {
+ final var peerId = peerInfo.getId();
+ final var voting = serverVotingStatusMap.get(peerId);
+ newServerInfoList.add(new ServerInfo(peerId, voting != null ? voting : peerInfo.isVoting()));
+ }
+
+ final var myId = raftContext.getId();
+ final var myVoting = serverVotingStatusMap.get(myId);
+ newServerInfoList.add(new ServerInfo(myId, myVoting != null ? myVoting : raftContext.isVotingMember()));
+
+ return newServerInfoList.build();
+ }
+ }
+
+ private class WaitingForLeaderElected extends OperationState {
+ private final ServerConfigurationPayload previousServerConfig;
+ private final ChangeServersVotingStatusContext operationContext;
+ private final Cancellable timer;
+
+ WaitingForLeaderElected(final ChangeServersVotingStatusContext operationContext,
+ final ServerConfigurationPayload previousServerConfig) {
+ this.operationContext = operationContext;
+ this.previousServerConfig = previousServerConfig;
+
+ timer = newTimer(raftContext.getConfigParams().getElectionTimeOutInterval(),
+ new ServerOperationTimeout(operationContext.getLoggingContext()));
+ }
+
+ @Override
+ void onNewLeader(final String newLeader) {
+ if (newLeader == null) {
+ return;
+ }
+
+ LOG.debug("{}: New leader {} elected", raftContext.getId(), newLeader);
+
+ timer.cancel();
+
+ if (raftActor.isLeader()) {
+ persistNewServerConfiguration(operationContext);
+ } else {
+ // Edge case - some other node became leader so forward the operation.
+ LOG.debug("{}: Forwarding {} to new leader", raftContext.getId(), operationContext.getOperation());
+
+ // Revert the local server config change.
+ raftContext.updatePeerIds(previousServerConfig);
+
+ changeToIdleState();
+ RaftActorServerConfigurationSupport.this.onNewOperation(operationContext);
+ }
+ }
+
+ @Override
+ void onServerOperationTimeout(final ServerOperationTimeout timeout) {
+ LOG.warn("{}: Leader election timed out - cannot apply operation {}",
+ raftContext.getId(), timeout.getLoggingContext());
+
+ // Revert the local server config change.
+ raftContext.updatePeerIds(previousServerConfig);
+ raftActor.initializeBehavior();
+
+ tryToForwardOperationToAnotherServer();
+ }