+ private void onShutDown() {
+ LOG.debug("{}: onShutDown", persistenceId());
+
+ if (shuttingDown) {
+ return;
+ }
+
+ shuttingDown = true;
+
+ final RaftActorBehavior currentBehavior = context.getCurrentBehavior();
+ switch (currentBehavior.state()) {
+ case Leader:
+ case PreLeader:
+ // Fall-through to more work
+ break;
+ default:
+ // For non-leaders shutdown is a no-op
+ self().tell(PoisonPill.getInstance(), self());
+ return;
+ }
+
+ if (context.hasFollowers()) {
+ initiateLeadershipTransfer(new RaftActorLeadershipTransferCohort.OnComplete() {
+ @Override
+ public void onSuccess(final ActorRef raftActorRef) {
+ LOG.debug("{}: leader transfer succeeded - sending PoisonPill", persistenceId());
+ raftActorRef.tell(PoisonPill.getInstance(), raftActorRef);
+ }
+
+ @Override
+ public void onFailure(final ActorRef raftActorRef) {
+ LOG.debug("{}: leader transfer failed - sending PoisonPill", persistenceId());
+ raftActorRef.tell(PoisonPill.getInstance(), raftActorRef);
+ }
+ }, null, TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS));
+ } else {
+ pauseLeader(new TimedRunnable(context.getConfigParams().getElectionTimeOutInterval(), this) {
+ @Override
+ protected void doRun() {
+ self().tell(PoisonPill.getInstance(), self());
+ }
+
+ @Override
+ protected void doCancel() {
+ self().tell(PoisonPill.getInstance(), self());
+ }
+ });
+ }
+ }
+
+ private void onLeaderTransitioning(final LeaderTransitioning leaderTransitioning) {
+ LOG.debug("{}: onLeaderTransitioning: {}", persistenceId(), leaderTransitioning);
+ Optional<ActorRef> roleChangeNotifier = getRoleChangeNotifier();
+ if (getRaftState() == RaftState.Follower && roleChangeNotifier.isPresent()
+ && leaderTransitioning.getLeaderId().equals(getCurrentBehavior().getLeaderId())) {
+ roleChangeNotifier.get().tell(newLeaderStateChanged(getId(), null,
+ getCurrentBehavior().getLeaderPayloadVersion()), getSelf());
+ }
+ }
+
+ private void switchBehavior(final SwitchBehavior message) {
+ if (!getRaftActorContext().getRaftPolicy().automaticElectionsEnabled()) {
+ RaftState newState = message.getNewState();
+ if (newState == RaftState.Leader || newState == RaftState.Follower) {
+ getRaftActorContext().getTermInformation().updateAndPersist(message.getNewTerm(), "");
+ switchBehavior(behaviorStateTracker.capture(getCurrentBehavior()),
+ AbstractRaftActorBehavior.createBehavior(context, message.getNewState()));
+ } else {
+ LOG.warn("Switching to behavior : {} - not supported", newState);
+ }
+ }
+ }
+
+ private void switchBehavior(final BehaviorState oldBehaviorState, final RaftActorBehavior nextBehavior) {
+ setCurrentBehavior(nextBehavior);
+ handleBehaviorChange(oldBehaviorState, nextBehavior);
+ }
+
+ @VisibleForTesting
+ RaftActorSnapshotMessageSupport newRaftActorSnapshotMessageSupport() {
+ return new RaftActorSnapshotMessageSupport(context, getRaftActorSnapshotCohort());