Skip to content

Commit

Permalink
preliminary work on indexed-v1 feed format
Browse files Browse the repository at this point in the history
  • Loading branch information
staltz committed Sep 7, 2022
1 parent 3e2ec7b commit b603673
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 278 deletions.
14 changes: 1 addition & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,8 @@ shows the implementation for 'classic' ed25519 SSB feeds.
```js
{
name: 'classic',
// In case `isFeed` needs to load some state asynchronously
prepareForIsFeed(sbot, feedId, cb) {
cb()
},
// used in request, block, cleanClock, sbot.post, vectorClock
isFeed(sbot, feedId) {
isFeed(feedId) {
return ref.isFeed(feedId)
},
getAtSequence(sbot, pair, cb) {
Expand All @@ -146,14 +142,6 @@ shows the implementation for 'classic' ed25519 SSB feeds.
cb(err && err.fatal ? err : null, msg)
})
},
// used in onAppend
convertMsg(msgVal) {
return msgVal
},
// used in vectorClock
isReady(sbot) {
return Promise.resolve(true)
},

// used in ebt:stream to distinguish between messages and notes
isMsg(msgVal) {
Expand Down
51 changes: 51 additions & 0 deletions formats/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module.exports = function ebtFormatFrom(feedFormat) {
return {
name: feedFormat.name,

// used in request, block, cleanClock, sbot.post, vectorClock
isFeed(feedId) {
return feedFormat.isAuthor(feedId)
},

getAtSequence(sbot, pair, cb) {
if (sbot.getAtSequenceNativeMsg) {
sbot.getAtSequenceNativeMsg(
[pair.id, pair.sequence],
feedFormat.name,
(err, nativeMsg) => {
if (err) cb(err)
else cb(null, nativeMsg)
}
)
} else {
sbot.getAtSequence([pair.id, pair.sequence], (err, msg) => {
if (err) cb(err)
else cb(null, msg.value)
})
}
},

appendOpts: { feedFormat: feedFormat.name },

appendMsg(sbot, msgVal, cb) {
function done(err) {
if (err && err.fatal) cb(err)
else cb()
}
if (sbot.db) {
sbot.db.add(msgVal, this.appendOpts, done)
} else {
sbot.add(msgVal, done)
}
},

// used in ebt:stream to distinguish between messages and notes
isMsg: feedFormat.isNativeMsg,

// used in ebt:events
getMsgAuthor: feedFormat.getFeedId,

// used in ebt:events
getMsgSequence: feedFormat.getSequence,
}
}
58 changes: 2 additions & 56 deletions formats/bendy-butt.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,4 @@
const SSBURI = require('ssb-uri2')
const ebtFormatFrom = require('./base')
const bendyButt = require('ssb-bendy-butt/format')

const appendOpts = { feedFormat: 'bendybutt-v1' }

module.exports = {
name: 'bendybutt-v1',
prepareForIsFeed(sbot, feedId, cb) {
cb()
},
// used in request, block, cleanClock, sbot.post, vectorClock
isFeed(sbot, feedId) {
return SSBURI.isBendyButtV1FeedSSBURI(feedId)
},
getAtSequence(sbot, pair, cb) {
sbot.getAtSequence([pair.id, pair.sequence], (err, msg) => {
cb(err, msg ? bendyButt.toNativeMsg(msg.value) : null)
})
},
appendMsg(sbot, buffer, cb) {
sbot.db.add(buffer, appendOpts, (err, msg) => {
cb(err && err.fatal ? err : null, msg)
})
},
convertMsg(sbot, msgVal, cb) {
cb(null, bendyButt.toNativeMsg(msgVal))
},
// used in vectorClock
isReady(sbot) {
return Promise.resolve(true)
},

// used in ebt:stream to distinguish between messages and notes
isMsg(bbVal) {
if (Buffer.isBuffer(bbVal)) {
const msgVal = bendyButt.fromNativeMsg(bbVal)
return msgVal && SSBURI.isBendyButtV1FeedSSBURI(msgVal.author)
} else {
return bbVal && SSBURI.isBendyButtV1FeedSSBURI(bbVal.author)
}
},
// used in ebt:events
getMsgAuthor(bbVal) {
if (Buffer.isBuffer(bbVal)) {
return bendyButt.fromNativeMsg(bbVal).author
} else {
return bbVal.author
}
},
// used in ebt:events
getMsgSequence(bbVal) {
if (Buffer.isBuffer(bbVal)) {
return bendyButt.fromNativeMsg(bbVal).sequence
} else {
return bbVal.sequence
}
},
}
module.exports = ebtFormatFrom(bendyButt)
48 changes: 6 additions & 42 deletions formats/buttwoo.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,13 @@
const butt2 = require('ssb-buttwoo/format')

const appendOpts = { encoding: 'bipf', feedFormat: 'buttwoo-v1' }
const ebtFormatFrom = require('./base')
const buttwoo = require('ssb-buttwoo/format')

module.exports = {
name: 'buttwoo-v1',
prepareForIsFeed(sbot, feedId, cb) {
cb()
},
// used in request, block, cleanClock, sbot.post, vectorClock
isFeed(sbot, feedId) {
return butt2.isAuthor(feedId)
},
getAtSequence(sbot, pair, cb) {
sbot.getAtSequenceNativeMsg(
[pair.id, pair.sequence],
'buttwoo-v1',
(err, nativeMsg) => {
if (err) cb(err)
else cb(null, nativeMsg)
}
)
},
appendMsg(sbot, buffer, cb) {
sbot.db.add(buffer, appendOpts, (err) => {
if (err && err.fatal) cb(err)
else cb()
})
},
// not used
convertMsg(sbot, msgVal, cb) {},
// used in vectorClock
isReady(sbot) {
return Promise.resolve(true)
},
...ebtFormatFrom(buttwoo),

appendOpts: { encoding: 'bipf', feedFormat: buttwoo.name },

// used in ebt:stream to distinguish between messages and notes
// Optimization
isMsg(bufferOrMsgVal) {
return Buffer.isBuffer(bufferOrMsgVal)
},
// used in ebt:events
getMsgAuthor(bufferOrMsgVal) {
return butt2.getFeedId(bufferOrMsgVal)
},
// used in ebt:events
getMsgSequence(bufferOrMsgVal) {
return butt2.getSequence(bufferOrMsgVal)
},
}
49 changes: 4 additions & 45 deletions formats/classic.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,15 @@
const ref = require('ssb-ref')

const appendOpts = { feedFormat: 'classic' }
const ebtFormatFrom = require('./base')
const classic = require('ssb-classic/format')

module.exports = {
name: 'classic',
prepareForIsFeed(sbot, feedId, cb) {
cb()
},
// used in request, block, cleanClock, sbot.post, vectorClock
isFeed(sbot, feedId) {
return ref.isFeed(feedId)
},
getAtSequence(sbot, pair, cb) {
sbot.getAtSequence([pair.id, pair.sequence], (err, msg) => {
cb(err, msg ? msg.value : null)
})
},
appendMsg(sbot, msgVal, cb) {
if (sbot.db) {
sbot.db.add(msgVal, appendOpts, (err, msg) => {
cb(err && err.fatal ? err : null, msg)
})
} else {
sbot.add(msgVal, (err, msg) => {
cb(err && err.fatal ? err : null, msg)
})
}
},
// used in onAppend
convertMsg(sbot, msgVal, cb) {
cb(null, msgVal)
},
// used in vectorClock
isReady(sbot) {
return Promise.resolve(true)
},
...ebtFormatFrom(classic),

// used in ebt:stream to distinguish between messages and notes
isMsg(msgVal) {
return (
classic.isNativeMsg(msgVal) &&
Number.isInteger(msgVal.sequence) &&
msgVal.sequence > 0 &&
ref.isFeed(msgVal.author) &&
msgVal.content
)
},
// used in ebt:events
getMsgAuthor(msgVal) {
return msgVal.author
},
// used in ebt:events
getMsgSequence(msgVal) {
return msgVal.sequence
},
}
65 changes: 20 additions & 45 deletions formats/indexed.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,31 @@
const pify = require('promisify-4loc')
const ref = require('ssb-ref')
const { QL0 } = require('ssb-subset-ql')
const indexed = require('../indexed-feed-format')
const ebtFormatFrom = require('./base')

module.exports = {
name: 'indexed',
prepareForIsFeed(sbot, feedId, cb) {
sbot.metafeeds.ensureLoaded(feedId, cb)
},
isFeed(sbot, author) {
const info = sbot.metafeeds.findByIdSync(author)
return info && info.feedpurpose === 'index'
},
...ebtFormatFrom(indexed),

appendMsg(sbot, msgTuple, cb) {
const [msgVal, payload] = msgTuple
sbot.db.addTransaction([msgVal], [payload], cb)
sbot.db.add(msgVal, this.appendOpts, (err) => {
if (err) {
return cb(err)
}
sbot.db.addOOO(payload, { feedFormat: 'classic' }, (err) => {
cb(err)
})
})
// FIXME: addTransaction should support heterogenous feed formats
// FIXME: indexed-feed-format needs to support validateBatch/BatchOOO
// sbot.db.addTransaction([msgVal], [payload], cb)
},

getAtSequence(sbot, pair, cb) {
sbot.getAtSequence([pair.id, pair.sequence], (err, msg) => {
if (err) return cb(err)

module.exports.convertMsg(sbot, msg.value, cb)
})
},
convertMsg(sbot, msgVal, cb) {
const { sequence } = msgVal.content.indexed
const authorInfo = sbot.metafeeds.findByIdSync(msgVal.author)
if (!authorInfo) return cb(new Error('Unknown author:' + msgVal.author))
const { author } = QL0.parse(authorInfo.metadata.query)
sbot.getAtSequence([author, sequence], (err, indexedMsg) => {
if (err) return cb(err)

cb(null, [msgVal, indexedMsg.value])
sbot.db.get(msg.value.content.indexed.key, (err, indexedMsgVal) => {
if (err) return cb(err)
cb(null, [msg.value, indexedMsgVal])
})
})
},
isReady(sbot) {
return pify(sbot.metafeeds.loadState)()
},
isMsg(msgTuple) {
if (Array.isArray(msgTuple) && msgTuple.length === 2) {
const [msgVal, payload] = msgTuple
return (
Number.isInteger(msgVal.sequence) &&
msgVal.sequence > 0 &&
ref.isFeed(msgVal.author) &&
msgVal.content
)
} else return false
},
getMsgAuthor(msgTuple) {
return msgTuple[0].author
},
getMsgSequence(msgTuple) {
return msgTuple[0].sequence
},
}
Loading

0 comments on commit b603673

Please sign in to comment.