Fix missing onChange event when following a leader with greater term

old-master
Vitaliy Filippov 2024-05-16 23:26:02 +03:00
parent 63610f0298
commit aba4525570
2 changed files with 40 additions and 0 deletions

View File

@ -182,9 +182,14 @@ class TinyRaft extends EventEmitter
if (msg.term > this.term)
{
this.term = msg.term;
this.state = FOLLOWER;
this.followers = null;
this.leader = msg.leader;
this.votes = {};
this.emit('change', { state: this.state, term: this.term, leader: this.leader });
// Repeat VOTE to the leader to join it
this.send(this.leader, { type: VOTE, term: this.term, leader: this.leader, priority: msg.priority });
return;
}
// add <from> as voter for <msg.leader>
this.votes[msg.leader] = this.votes[msg.leader] || [];

View File

@ -311,6 +311,40 @@ async function testLeaderPriority()
console.log('testLeaderPriority: OK');
}
async function testPartition1_3()
{
console.log('testPartition1_3');
const partitions = { '1-3': true, '3-1': true };
const nodes = newNodes(3, partitions, cfg => cfg.nodes = [ 1, 2, 3 ]);
let leaderChanges = 0, prevLeader = null;
nodes[2].on('change', (st) =>
{
if (st.leader && st.leader != prevLeader)
{
prevLeader = st.leader;
leaderChanges++;
}
});
// Check that 3 nodes are in quorum after 2000ms
// 2 is always elected as leader because it's the first node that can determine
// that the first voting round has failed: it receives a vote for 1 from 1 and
// a vote for 3 from 3. So it knows that no node can get 2 votes. 1 and 3, at
// the same time, don't know it for sure because they don't receive failures
// from each other due to the network partition.
await new Promise(ok => setTimeout(ok, 2000));
checkQuorum(nodes, 3);
if (leaderChanges >= 3)
{
throw new Error('More than 3 leader changes in 2000ms: '+leaderChanges);
}
// Clean up
for (const id in nodes)
{
nodes[id].stop();
}
console.log('testLeadershipExpiration: OK');
}
async function run()
{
await testStartThenRemoveNode();
@ -319,6 +353,7 @@ async function run()
await testRestart();
await testChangeNodes();
await testLeaderPriority();
await testPartition1_3();
process.exit(0);
}