Liferaft
Consensus protocol based on raft, but only for saving lifes and works in node as well as in browers.
Install / Use
/learn @unshiftio/LiferaftREADME
liferaft
liferaft is an JavaScript implementation of the [Raft] consensus algorithm.
Installation
The liferaft module is distributed through npm and is compatible with
browserify as well as node.js. You can install this module using:
npm install --save liferaft
Table Of Contents
Usage
In all examples we assume that you've imported the liferaft module as
following:
'use strict';
var LifeRaft = require('liferaft')
, raft = new Raft('address', { /* optional options */});
Please note that the instructions for Node.js and browser are exactly the same as we assume that your code will be compiled using a [Browserify] based system. The only major difference is that you probably don't need to configure a commit and append log (but this of course, fully optional).
The LifeRaft library is quite dumb by default. We try to be as lean and
extendible as possible so you, as a developer, have complete freedom on how you
want to implement Raft in your architecture. This also means that we ship this
library without any build in transport. This allows you to use it with your
existing technology stack and environment. If you want to use SharedWorkers as
transport in the browser? Awesome, you can do that. Want to use it on node?
There are literally thousands of different transport libraries that you can use.
Configuration
There are a couple of default options that you can configure in the constructor of your Raft:
addressA unique address of the node that we just created. If none is supplied we will generate a random UUID.heartbeatThe heartbeat timeout. Make sure that this value is lower then your minimum election timeout and take message latency in consideration when specifying this and the minimum election value.election minMinimum election timeout.election maxMaximum election timeout.thresholdThreshold for when the heartbeat and latency is to close to the minimum election timeout.Log: An Log compatible constructor we which use for state and data replication.
The timeout values can be configured with either a number which represents the
time milliseconds or a human readable time string such as 10 ms. The heartbeat
timeouts are used to detect a disconnection from the LEADER process if no
message has been received within the given timeout we assume its dead that we
should be promoted to master. The election timeout is the time it may take to
reach a consensus about the master election process. If this times out, we will
start another re-election.
var raft = new Raft({
'address': 'tcp://localhost:8089',
'election min': '200 millisecond',
'election max': '1 second'
});
As you might have noticed we're using two different styles of passing in the address to the raft instance, as address property in the options and as first argument in the constructor.
Events
The liferaft module is an EventEmitter at it's core and is quite chatty
about the events it emits.
Event | Description
--------------------|------------------------------------------------------
term change | The term has changed.
leader change | We're now following a newly elected leader.
state change | Our state/role changed.
heartbeat timeout | Heartbeat timeout, we're going to change to candidate.
data | Emitted by you, so we can work with the data.
vote | We've received a vote request.
leave | Node has been removed from the cluster.
join | Node has been added to the cluster.
end | This Raft instance has ended.
initialize | The node has been fully initialized.
error | An error happened while doing.. Things!
threshold | The heartbeat timeout is getting close to election timeout.
leader | Our state changed to leader.
follower | Our state changed to follower.
candidate | Our state changed to candidate.
stopped | Our state changed to stopped.
heartbeat | The leader is about to send a heartbeat message.
commit | A command has been saved to the majority of node's logs
Please note that the following properties are exposed on the constructor not
on the prototype.
LifeRaft.states
This is an array that contains the names of the states. It can be used to create a human readable string from your current state.
console.log(LifeRaft.states[raft.state]); // FOLLOWER
LifeRaft.{FOLLOWER,LEADER,CANDIDATE,STOPPED,CHILD}
These are the values that we set as state. If you instance is a leader it's
state will be set to LifeRaft.LEADER.
The rest of these properties are exposed on the LifeRaft prototype
LifeRaft#type(of)
Check the type of the given thing. This returns the correct type for arrays,
objects, regexps and all the things. It's used internally in the library but
might be useful for you as user as well. The function requires one argument
which would be the thing who's type you need figure out.
raft.type([]); // array
raft.type({}); // object
LifeRaft#quorum(responses)
Check if we've reached our quorum (a.k.a. minimum amount of votes requires for a voting round to be considered valid) for the given amount of votes. This depends on the amount of joined nodes. It requires one argument which is the amount of responses that have been received.
raft.join('tcp://127.0.0.1');
raft.join('tcp://127.0.0.2');
raft.join('tcp://127.0.0.3');
raft.join('tcp://127.0.0.4');
raft.join('tcp://127.0.0.4');
raft.quorum(5); // true
raft.quorum(2); // false
LifeRaft#majority()
Returns the majority that needs to be reached for our quorum.
raft.majority(); // 4
LifeRaft#indefinitely(attempt, fn, timeout)
According to section 5.3 of the Raft paper it's required that we retry sending
the RPC messages until they succeed. This function will run the given attempt
function until the received callback has been called successfully and within our
given timeout. If this is not the case we will call the attempt function again
and again until it succeeds. The function requires 3 arguments:
attempt, The function that needs to be called over and over again until he calls the receiving callback successfully and without errors as we assume an error first callback pattern.fn, Completion callback, we've successfully executed the attempt.timeout, Time the attempt is allowed to take.
raft.indefinitely(function attemp(next) {
dosomething(function (err, data) {
//
// if there is no error then we wil also pass the data to the completion
// callback.
//
return next(err, data);
});
}, function done(data) {
// Successful execution.
}, 1000);
LifeRaft#packet(type, data)
Generate a new packet object that can be transfered to a client. The method accepts 2 arguments:
type, Type of packet that we want to transfer.data, Data that should be transfered.
var packet = raft.packet('vote', { foo: 'bar' });
These packages will contain the following information:
stateIf we are aLEADER,FOLLOWERorCANDIDATEtermOur current term.addressThe address of this node.leaderThe address of our leader.lastIf logs are enabled we also include the last committed term and index.
And of course also the type which is the type you passed this function in and
the data that you want to send.
LifeRaft#message(who, what, when)
The message method is somewhat private but it might also be useful for you as developer. It's a message interface between every connected node in your cluster. It allows you to send messages the current leader, or only the followers or everybody. This allows you easily build other scale and high availability patterns on top of this module and take advantage of all the features that this library is offering. This method accepts 2 arguments:
who, The messaging pattern/mode you want it use. It can either be:
LifeRaft.LEADER: Send message to the current leader.LifeRaft.FOLLOWER: Send to everybody who is not a leader.LifeRaft.CHILD: Send to every child in the cluster (everybody).<node address>: Fin
Related Skills
node-connect
344.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
99.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
