From 399d0a666d1f8d2956c81279a98bed3c483dea51 Mon Sep 17 00:00:00 2001 From: cel Date: Mon, 25 Dec 2017 12:42:41 -1000 Subject: Allow using ooo (out-of-order message replication) --- lib/app.js | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) (limited to 'lib/app.js') diff --git a/lib/app.js b/lib/app.js index 4789e11..81f58f5 100644 --- a/lib/app.js +++ b/lib/app.js @@ -32,6 +32,7 @@ function App(sbot, config) { this.msgFilter = conf.filter this.showPrivates = conf.showPrivates == null ? true : conf.showPrivates this.previewVotes = conf.previewVotes == null ? false : conf.previewVotes + this.useOoo = conf.ooo == null ? false : conf.ooo var base = conf.base || '/' this.opts = { @@ -44,7 +45,11 @@ function App(sbot, config) { sbot.get = memo({cache: lru(100)}, sbot.get) this.about = new About(this, sbot.id) - this.getMsg = memo({cache: lru(100)}, getMsgWithValue, sbot) + this.msgCache = lru(100) + this.getMsg = memo({cache: this.msgCache}, getMsgWithValue, sbot) + this.getMsgOoo = sbot.ooo + ? memo({cache: this.msgCache}, sbot.ooo.get) + : function (id, cb) { cb(new Error('missing ssb-ooo plugin')) } this.getAbout = memo({cache: this.aboutCache = lru(500)}, this._getAbout.bind(this)) this.unboxContent = memo({cache: lru(100)}, sbot.private.unbox) @@ -179,6 +184,14 @@ App.prototype.getMsgDecrypted = function (key, cb) { }) } +App.prototype.getMsgDecryptedOoo = function (key, cb) { + var self = this + this.getMsgOoo(key, function (err, msg) { + if (err) return cb(err) + self.unboxMsg(msg, cb) + }) +} + App.prototype.publish = function (content, cb) { var self = this function tryPublish(triesLeft) { @@ -333,6 +346,16 @@ function getMsgWithValue(sbot, id, cb) { }) } +function getMsgOooWithValueCreate(sbot) { + if (!sbot.ooo) { + var err = new Error('missing ssb-ooo plugin') + return function (id, cb) { + cb(null, err) + } + } + return sbot.ooo.get +} + App.prototype._getAbout = function (id, cb) { var self = this if (!u.isRef(id)) return cb(null, {}) @@ -805,3 +828,85 @@ App.prototype.getIdeaTitle = function (id, cb) { }) ) } + +function traverse(obj, emit) { + emit(obj) + if (obj !== null && typeof obj === 'object') { + for (var k in obj) { + traverse(obj[k], emit) + } + } +} + +App.prototype.expandOoo = function (opts, cb) { + var self = this + var dest = opts.dest + var msgs = opts.msgs + if (!Array.isArray(msgs)) return cb(new TypeError('msgs should be array')) + + // algorithm: + // traverse all links in the initial message set. + // find linked-to messages not in the set. + // fetch those messages. + // if one links to the dest, add it to the set + // and look for more missing links to fetch. + // done when no more links to fetch + + var msgsO = {} + var getting = {} + var waiting = 0 + + function checkDone() { + if (waiting) return + var msgs = Object.keys(msgsO).map(function (key) { + return msgsO[key] + }) + cb(null, msgs) + } + + function getMsg(id) { + if (msgsO[id] || getting[id]) return + getting[id] = true + waiting++ + self.getMsgDecryptedOoo(id, function (err, msg) { + waiting-- + if (err) console.trace(err) + else gotMsg(msg) + checkDone() + }) + } + + var links = {} + function addLink(id) { + if (typeof id === 'string' && id[0] === '%' && u.isRef(id)) { + links[id] = true + } + } + + msgs.forEach(function (msg) { + if (msgs[msg.key]) return + if (msg.value.content === false) return // missing root + msgsO[msg.key] = msg + traverse(msg, addLink) + }) + waiting++ + for (var id in links) { + getMsg(id) + } + waiting-- + checkDone() + + function gotMsg(msg) { + if (msgsO[msg.key]) return + var links = [] + var linkedToDest = msg.key === dest + traverse(msg, function (id) { + if (id === dest) linkedToDest = true + links.push(id) + }) + if (linkedToDest) { + msgsO[msg.key] = msg + links.forEach(addLink) + } + } +} -- cgit v1.2.3