automenta / telepathine

p2p gossip protocol w/ incremental diffs & failure detection for a fault-tolerant, self-managing cluster or mesh (for node.js)
Other
14 stars 1 forks source link

Telepathine for Node.JS

NPM

unstable Dependency Status

Features

P2P "Gossip" protocol

Shared memory (distributed hashtable)

Distributed event bus

Incremental change-sets

Failure detection

Fault-tolerant

Self-managing cluster or mesh

TCP with optional UDP mode (connection-less for small packets)

Private Darknet with Pre-shared Network Encryption Key


API

See scripts in the simulations/ directory for examples.

Constructor

new Telepathine(port, seeds, options)

Default Options:

    options = {

        // For IPv4 use [a.b.c.d]:port, ex: 192.168.0.100:1234
        // For IPv6 use the format [ad:dre::ss]:port, ex: [::1]:9000
        address: '127.0.0.1', // localhost

        // Whether to emit value change events on heartbeats
        emitValueOnHeartBeat: false,

        // Manual Network address translation
        addressMap: {
            //key: value //key = address mapped from, value = address mapped to
        },

        // Network ID, used to encrypt messages, secured from non-network message.  undefined=public, no encryption
        network: "Preshared_Network_Key",

        udp: true,                  //whether to run UDP server (recommended)

        gossipIntervalMS: 2500,     //how often (ms) to send gossip updates

        heartbeatIntervalMS: 2500   //how often (ms) to send heartbeat updates

    };

Methods

start([callback]), stop()

set(key, value[, expiresAt])

get(key)

getRemote(peer, key)

getRemoteKeys(peer)

addPeer(address)

allPeers()

livePeers()

deadPeers()

say(eventname, parameter[, eventDurationMS, buffer])

hear(eventname, handler(data, fromPeer) )

hearOnce(eventname, handler(data, fromPeer) )

know(key, handler(peer_name, key, value, expiresAt))

believe(key, handler(peer_name, key, value, expiresAt))

after(delayMS, callback)

every(intervalMS, callback)

on(eventname, handler)

Events

on('start', function(peer) {})

on('stop', function(peer) {})

on('set', function(peer_name, key, value, expiresAt) {})

on('set:[key]', function(peer_name, key, value, expiresAt) {})

on('say:[eventname]', function(parameter, fromPeer) {})

on('key:expired', function(peer_name, key, value, expiresAt) {})

on('peer:new', function(peerstate) {})

on('peer:start', function(peer_name) {})

on('peer:stop', function(peer_name) {})

Examples

Distributed Shared Memory

From: simulation/example_p2p.js

//For debug log, run: DEBUG=* node examples/p2p.js

var T = require('../lib/telepathine.js').Telepathine;

var startPort = 9000;
var numSeeds = 4;

var seed = new T( startPort++,
                  [ /* no seeds */ ], 
                  { /* default configuration */ } 
                ).start();  

// Create peers and point them at the seed 
// Usually this would happen in separate processes.
// To prevent a network's single point of failure, design with multiple seeds.
for (var i = 0; i < numSeeds; i++) {

    var g = new T(i + startPort + 1, 
                  ['127.0.0.1:' + (startPort + i + 2)]).start();

    //event emitted when a remote peer sets a key to a value
    g.on('set', function (peer, k, v) {
        console.log(this.peer_name + " knows via on('set'.. that peer " + peer + " set " + k + "=" + v);
    });

    //convenience method for key/value change events
    g.know('somekey', function (peer, k, v) {
        console.log(this.peer_name + " knows via know('somekey'.. that peer " + peer + " set somekey=" + v);
    });

    //convenience method for key change events, using wildcard
    g.know('*', function (peer,k, v) {
        console.log(this.peer_name + " knows via know('*'.. that peer " + peer + " set " + this.event + "," + k + "=" + v);
    });
}

// Another peer which updates state after a delay
new T(startPort, 
      ['127.0.0.1:' + (startPort + 1)] )
        .after(1000, function () {

            // indefinite memory
            this.set('somekey', 'somevalue');

            // temporary memory: 10 seconds from now this key will start to expire in the gossip net
            this.set('somekey2', 'somevalue', Date.now() + 10000);

        }).start();

Distributed Event Bus

From: simulation/example_events.js

var a = new T(9000, []).start();
var b = new T(9001, [":9000"]).start();

a.on('start', function () {

    a.hearOnce('eventname', function (data, fromPeer) {
        console.log('a received eventname=', data, 'from', fromPeer);
        a.say('reply');
    });

    a.hear('*', function (data, fromPeer) {
        console.log('a received ', this.event, '=', data, 'from', fromPeer);
    });

});

b.on('start', function () {

    b.hearOnce('reply', function (data, fromPeer) {
        console.log('b received reply=', data, ' from ', fromPeer);
    });     

    b.say('eventname', 'eventdata');

});

Tests

expresso -I lib test/*  

...or:

npm test

Changes

This is a fork of grapevine which is a fork of the original node-gossip.

grape·vine (grāp′vīn′) n.

  1. A vine on which grapes grow.
  2. a. The informal transmission of information, gossip, or rumor from person to person. b. A usually unrevealed source of confidential information.

node-gossip implements a gossip protocol w/failure detection, allowing you to create a fault-tolerant, self-managing cluster of node.js processes. Each server in the cluster has it's own set of key-value pairs which are propogated to the others peers in the cluster. The API allows you to make changes to the local state, listen for changes in state, listen for new peers and be notified when a peer appears to be dead or appears to have come back to life.

The module is currently in 'hey it seems to work for me' state, there are probably some bugs lurking around. The API will probably change and suggestions on how to improve it are very welcome.

TODO

References

Gossip Protocol

Both the gossip protocol and the failure detection algorithms are based off of academic papers and Cassandra's (http://www.cassandra.org/) implementation of those papers. This library is highly indebted to both.

Scuttlebutt