Compare commits
No commits in common. "b8701b4aa7c06086c1e91cd8887bee9f5d487534" and "c4cc30027ab0247eda9a647c406c47a275c9cc80" have entirely different histories.
b8701b4aa7
...
c4cc30027a
33
tinyraft.js
33
tinyraft.js
|
@ -188,36 +188,41 @@ class TinyRaft extends EventEmitter
|
|||
{
|
||||
this.leader = msg.leader;
|
||||
this.term = msg.term;
|
||||
this.state = CANDIDATE;
|
||||
this.state = FOLLOWER;
|
||||
this.followers = null;
|
||||
this._nextTerm(this.heartbeatTimeout*2 + this.electionTimeout);
|
||||
this.emit('change', { state: this.state, term: this.term, leader: this.leader });
|
||||
}
|
||||
this.send(from, { type: VOTE, term: this.term, leader: this.leader });
|
||||
}
|
||||
else if (msg.type == VOTE && msg.term == this.term)
|
||||
else if (msg.type == VOTE)
|
||||
{
|
||||
if (msg.term == this.term)
|
||||
{
|
||||
this.voted++;
|
||||
this.votes[msg.leader] = this.votes[msg.leader] || [];
|
||||
this.votes[msg.leader].push(from);
|
||||
const n = this.votes[msg.leader].length;
|
||||
if (n == 1 + (0 | this.nodes.length/2) && msg.leader == this.nodeId)
|
||||
if (n > this.nodes.length/2 && n-1 <= this.nodes.length/2)
|
||||
{
|
||||
this.leader = msg.leader;
|
||||
this.state = LEADER;
|
||||
this.state = (this.leader == this.nodeId ? LEADER : FOLLOWER);
|
||||
if (this.state == LEADER)
|
||||
{
|
||||
this._nextTerm(this.leadershipTimeout > 0 ? this.leadershipTimeout : -1);
|
||||
this.followers = this.votes[this.nodeId];
|
||||
for (const follower of this.followers)
|
||||
{
|
||||
// Send a heartbeat to confirm leadership
|
||||
this.send(follower, { type: PING, term: this.term });
|
||||
}
|
||||
this.emit('change', { state: this.state, term: this.term, leader: this.nodeId, followers: this.votes[this.nodeId] });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.followers = null;
|
||||
this._nextTerm(this.heartbeatTimeout*2 + this.electionTimeout);
|
||||
this.emit('change', { state: this.state, term: this.term, leader: this.leader });
|
||||
}
|
||||
}
|
||||
else if (n > this.nodes.length/2 && this.state == LEADER && msg.leader == this.nodeId)
|
||||
{
|
||||
this.followers = this.votes[this.nodeId];
|
||||
// Send a heartbeat to confirm leadership
|
||||
this.send(from, { type: PING, term: this.term });
|
||||
this.emit('change', { state: this.state, term: this.term, leader: this.nodeId, followers: this.votes[this.nodeId] });
|
||||
}
|
||||
else if (this._isVotingFailed())
|
||||
|
@ -225,13 +230,9 @@ class TinyRaft extends EventEmitter
|
|||
this._nextTerm(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (msg.type == PING)
|
||||
{
|
||||
if (this.state == CANDIDATE && this.term == msg.term && from == this.leader)
|
||||
{
|
||||
this.state = FOLLOWER;
|
||||
this.emit('change', { state: this.state, term: this.term, leader: this.nodeId });
|
||||
}
|
||||
if (this.state == FOLLOWER && from == this.leader)
|
||||
{
|
||||
this.markAlive();
|
||||
|
|
|
@ -67,12 +67,12 @@ function checkQuorum(nodes, count)
|
|||
|
||||
function checkNoQuorum(nodes)
|
||||
{
|
||||
const nc = Object.values(nodes).filter(n => n.state != TinyRaft.CANDIDATE);
|
||||
if (nc.length > 0)
|
||||
const leaders = Object.values(nodes).filter(n => n.state == TinyRaft.LEADER);
|
||||
if (leaders.length > 0)
|
||||
{
|
||||
throw new Error('we have non-candidates ('+nc.map(n => n.nodeId).join(', ')+'), but we should not');
|
||||
throw new Error('we have a leader ('+leaders.map(n => n.nodeId).join(', ')+'), but we should not');
|
||||
}
|
||||
console.log('OK: '+Object.keys(nodes).length+' candidates, no quorum');
|
||||
console.log('OK: '+Object.keys(nodes).length+' nodes, no quorum');
|
||||
}
|
||||
|
||||
async function testStartThenRemoveNode()
|
||||
|
|
Loading…
Reference in New Issue