UNPKG

nodeway-raft

Version:

It is an implementation of the Raft consensus algorithm in Nodeway.

77 lines (71 loc) 2.64 kB
'use strict'; class Leader { constructor(node, currentTerm, log) { this.node = node; this.currentTerm = currentTerm; this.log = log; this.nextIndex = {}; this.matchIndex = {}; this.requestAppend(); } setHeartbeatInterval(heartbeatInterval) { this.heartbeatInterval = setInterval( this.requestAppend.bind(this), heartbeatInterval ); } clearHeartbeatInterval() { clearInterval(this.heartbeatInterval); } requestAppend(_id) { function replicate(id) { if (typeof this.nextIndex[id]==='undefined') this.nextIndex[id] = this.log.size()+1; if (typeof this.matchIndex[id]==='undefined') this.matchIndex[id] = 0; let prevLogIndex = this.nextIndex[id]-1, prevLogTerm = this.log.termAt(prevLogIndex), entry = this.log.entryAt(this.nextIndex[id]); return { term: this.currentTerm, prevLogIndex, prevLogTerm, entries: entry ? [entry] : [], commitIndex: this.log.commitIndex } } _id ? this.node.emit(_id, 'AppendEntries', replicate.bind(this)) : this.node.broadcast('AppendEntries', replicate.bind(this)); } onAppendEntries(id, args) { if (args.success) { this.nextIndex[id] = args.matchIndex+1; this.matchIndex[id] = args.matchIndex; let index = Object.keys(this.matchIndex) .map(id => this.matchIndex[id]) .concat(this.log.size()) .sort((a, b) => b-a), agree = this.node.majority(); if (agree < index.length && this.log.termAt(index[agree])===this.currentTerm) { let prevCommitIndex = this.log.commitIndex; this.log.commitIndex = index[agree]; if (this.log.commitIndex > prevCommitIndex) { setImmediate(this.requestAppend.bind(this)); return; } } } else { this.nextIndex[id] = Math.max(this.nextIndex[id]-1, 1); } this.nextIndex[id]<=this.log.size() && this.requestAppend(id); } appendEntry(entry, nocb) { entry.state = 'leader'; entry.term = this.currentTerm; entry.nocb = nocb; this.log.push(entry); this.node.majority() ? this.requestAppend() : this.log.commitIndex++; } } module.exports = Leader;