When a follower joins the cluster there is no new election if there is already a leader.
Actual behavior
To distributed the leaders across the cluster uniformly, we predefine the leaders for each partition. On bootstrap we promote these predefined leaders to candidate which triggers an election even if there is already a leader. If this node doesn't have the up-to-date log it cannot win the election. So it won't lead to an inconsistent state. However, the election cause leader changes unnecessarily.
Log
=== Bootstrap
6:24:51.515 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - No heartbeat from null in the last PT3.122S (calculated from last 3178 ms), sending poll requests
16:24:51.516 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to CANDIDATE
16:24:51.517 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.CandidateRole - RaftServer{raft-partition-partition-1}{role=CANDIDATE} - Starting election
16:24:51.534 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to LEADER
16:24:51.534 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Found leader 2
16:24:51.616 [] [raft-server-1-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Found leader 2
16:24:51.616 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Found leader 2
16:24:51.723 [] [raft-partition-group-raft-partition-0] INFO io.atomix.protocols.raft.partition.RaftPartitionGroup - Started
== Stop Node 0
16:24:55.644 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to INACTIVE
== Restart Node 0
16:25:01.478 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to CANDIDATE
16:25:01.515 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.CandidateRole - RaftServer{raft-partition-partition-1}{role=CANDIDATE} - Starting election
16:25:01.529 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.LeaderRole - RaftServer{raft-partition-partition-1}{role=LEADER} - Received greater term from 0
16:25:01.529 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to FOLLOWER
16:25:01.530 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to FOLLOWER
16:25:04.915 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - No heartbeat from null in the last PT3.379S (calculated from last 3385 ms), sending poll requests
16:25:05.466 [] [raft-server-1-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - No heartbeat from null in the last PT4.096S (calculated from last 4096 ms), sending poll requests
16:25:05.515 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - Accepted PollRequest{term=2, candidate=1, lastLogIndex=5, lastLogTerm=1}: candidate's log is up-to-date
16:25:05.515 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - Accepted PollRequest{term=2, candidate=1, lastLogIndex=5, lastLogTerm=1}: candidate's log is up-to-date
16:25:05.515 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - No heartbeat from null in the last PT3.979S (calculated from last 3986 ms), sending poll requests
16:25:05.515 [] [raft-server-1-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to CANDIDATE
16:25:05.515 [] [raft-server-0-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.FollowerRole - RaftServer{raft-partition-partition-1}{role=FOLLOWER} - Accepted PollRequest{term=2, candidate=2, lastLogIndex=5, lastLogTerm=1}: candidate's log is up-to-date
16:25:05.516 [] [raft-server-1-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.CandidateRole - RaftServer{raft-partition-partition-1}{role=CANDIDATE} - Starting election
16:25:05.516 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.impl.RaftContext - RaftServer{raft-partition-partition-1} - Transitioning to CANDIDATE
16:25:05.516 [] [raft-server-2-raft-partition-partition-1] INFO io.atomix.protocols.raft.roles.CandidateRole - RaftServer{raft-partition-partition-1}{role=CANDIDATE} - Starting election
Steps to reproduce
Create a cluster with 1 partition and replication factor 3 wait until the leaders are elected. If broker 0 is not the leader, restart it and then you can see the above behavior.
Expected behavior
When a follower joins the cluster there is no new election if there is already a leader.
Actual behavior
To distributed the leaders across the cluster uniformly, we predefine the leaders for each partition. On bootstrap we promote these predefined leaders to candidate which triggers an election even if there is already a leader. If this node doesn't have the up-to-date log it cannot win the election. So it won't lead to an inconsistent state. However, the election cause leader changes unnecessarily.
Log
Steps to reproduce
Create a cluster with 1 partition and replication factor 3 wait until the leaders are elected. If broker 0 is not the leader, restart it and then you can see the above behavior.
I will try to come up with code to reproduce it.