class Follower extends AbstractRaftActorBehavior {

    @Override
    public RaftActorBehavior handleMessage(final ActorRef sender, final Object message) {
        if (message instanceof ElectionTimeout || message instanceof TimeoutNow) {
            return handleElectionTimeout(message);
        }

        if (appendEntriesMessageAssembler.handleMessage(message, actor())) {
            return this;
        }

        if (!(message instanceof RaftRPC)) {
            // The rest of the processing requires the message to be a RaftRPC
            return null;
        }

        final RaftRPC rpc = (RaftRPC) message;
        // If RPC request or response contains term T > currentTerm:
        // set currentTerm = T, convert to follower (§5.1)
        // This applies to all RPC messages and responses
        if (rpc.getTerm() > context.getTermInformation().getCurrentTerm() && shouldUpdateTerm(rpc)) {
            log.info("{}: Term {} in \"{}\" message is greater than follower's term {} - updating term",
                logName(), rpc.getTerm(), rpc, context.getTermInformation().getCurrentTerm());

            context.getTermInformation().updateAndPersist(rpc.getTerm(), null);
        }

        if (rpc instanceof InstallSnapshot) {
            handleInstallSnapshot(sender, (InstallSnapshot) rpc);
            restartLastLeaderMessageTimer();
            scheduleElection(electionDuration());
            return this;
        }

        if (!(rpc instanceof RequestVote) || canGrantVote((RequestVote) rpc)) {
            restartLastLeaderMessageTimer();
            scheduleElection(electionDuration());
        }

        return super.handleMessage(sender, rpc);
    }

    public  Follower(final RaftActorContext context);
    public  Follower(final RaftActorContext context, final String initialLeaderId,
            final short initialLeaderPayloadVersion);

}