Node.js implementation of the Raft concensus algorithm.
- Persistence: LevelDB
- Protocol: Msgpack over TCP
(for the abstract implementation check skiff-algorithm).
$ npm install skiff
var Skiff = require('skiff');
var options = {
dbPath: '/path/to/my/leveldb/database/dir'
};
var node = Skiff('tcp+msgpack://localhost:8081', options);
autoListen
: start listening on bootup. defaults totrue
.transport
: transport type. Supported values:tcp-msgpack
: Msgpack over TCP (default)tcp-nlsjson
: New-line separated JSON over TCP
dbPath
: database pathwaitLeaderTimeout
: the time to wait to become a leader. defaults to 3000 (ms).standby
: if true, will start at thestandby
state instead of thefollower
state. In thestandby
state the node only waits for a leader to send commands. Defaults tofalse
.cluster
: the id of the cluster this node will be a part ofuuid
: function that generates a UUID. Defaults to using thecuid
package.heartbeatInterval
: the interval between heartbeats sent from leader. defaults to 50 ms.minElectionTimeout
: the minimum election timeout. defaults to 150 ms.maxElectionTimeout
: the maximum election timeout. defaults to 300 ms.commandTimeout
: the maximum amount of time you're willing to wait for a command to propagate. Defaults to 3 seconds. You can override this in each command call.retainedLogEntries
: the maximum number of log entries that are committed to the state machine that should remain in memory. Defaults to 50.
A skiff client object implements the level-up API.
You can also extend the client with level-* plugins, including sublevel.
Other than that, you can:
Listen for nodes connecting to us.
Joins a node given its URL.
Leaves a node given its URL.
To boot a cluster, start a node and wait for it to become a leader. Then, create each additional node in the standby
mode (options.standby: true
) and do leader.join(nodeURL)
.
See this test for an actual implementation.
A Skiff node emits a bunch of events that may or not interest you. In no particular order:
error (error)
- if something goes terribly bad.warning (warning)
- if something goes mildly bad.loaded
- once the node persisted state is loaded on bootupapplied log (logIndex)
- after a certain log index is applied to the state machine.election timeout
- when a node detects a timeout and will become a candidate because of that.joined (peer)
- when a node joins a given peer.connected(peer)
- when a node is connected to a given peer.disconnected(peer)
- when a node is disconnected from a peer.connecting(peer)
- when a node is trying to connect to a peer.reconnected(peer)
- when a node is reconnected to a peer.outgoing call (peer, type, args)
- when a node sends an RPC call to a peer.response (peer, err, args)
- when a node receives a response from a peer.left (peer)
- when a node leaves a peerstate (state)
- after a node has transitioned to a given stateleader (node)
- after a node has transitioned to the leader statecandidate (node)
- after a node has transitioned to the candidate statefollower (node)
- after a node has transitioned to the follower statestopped (node)
- after a node has transitioned to the stopped statestandby (node)
- after a node has transitioned to the standby stateRequestVote (args)
- when a node receives a RequestVote RPC callAppendEntries (args)
- when a node receives an AppendEntries RPC callInstallSnapshot (args)
- when a node receives an InstallSnapshot RPC callreply (args)
- once a node has replied to an RPC call
ISC