UNPKG

plasmid

Version:

A low-level implementation of the anti-entropy gossip protocol scuttlebutt.

91 lines (73 loc) 2.37 kB
'use strict' var LocalState = require('./states/local') var Host = module.exports = function(id, opts) { this.id = id this.opts = opts || {} if (!this.opts.state) this.opts.state = new LocalState({}) this.state = this.opts.state.create(id) } var GossipTransform = require('./transform') Host.prototype.exchange = function() { return new GossipTransform(this) } var GossipStream = require('./stream') Host.prototype.createStream = function(opts) { return new GossipStream(this, opts) } // = {(r,max(μp(r))) | r ∈ P} Host.prototype.getDigest = function() { var digest = [] // randomize this.state.digest().forEach(function(s) { digest.splice(randomBetween(0, digest.length), 0, s) }) return digest } // = {(r,k,v,n) | μp(r)(k) = (v,n) ∧ n > max(μq(r))} Host.prototype.getDeltas = function(digest, result) { var deltas = Object.create(null), ids = [] if (!result) result = [] digest.forEach(function(s) { if (!this.state.knows(s.r)) return deltas[s.r] = this.state.history(s.r, s.n) ids.splice(randomBetween(0, ids.length), 0, s.r) }, this) if (!ids.length) return [] // scuttle-breadth ordering - tries to be fair to all participants // (1) order deltas from same participant inversely by their version number // (2) rank deltas from the same participant incrementally (order by rank) // (3) shuffle deltas of the same rank if (this.opts.ordering === 'breadth') { while (ids.length) { for (var i = ids.length - 1; i >= 0; --i) { var id = ids[i] result.push(deltas[id].shift()) if (!deltas[id].length) ids.splice(ids.indexOf(id), 1) } } } // scuttle-depth ordering // (1) order deltas from same participant inversely by their version number // (2) order by count of available deltas // (3) shuffle participants with the same number of available deltas else { ids.sort(function(lhs, rhs) { return deltas[rhs].length - deltas[lhs].length }) ids.forEach(function(id) { deltas[id].forEach(function(delta) { result.push(delta) }) }, this) } return result } Host.prototype.get = function(key) { return this.state.get(key) } Host.prototype.set = function(key, value) { this.state.set(key, value) } function randomBetween(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min }