Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

indexed-v1 feed format #71

Merged
merged 4 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 3 additions & 5 deletions benchmark/classic-vs-buttwoo.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ const caps = require('ssb-caps')
const rimraf = require('rimraf')
const mkdirp = require('mkdirp')
const ssbKeys = require('ssb-keys')
const bendyButt = require('ssb-bendy-butt/format')
const butt2 = require('ssb-buttwoo/format')
const classic = require('ssb-classic/format')
const bfe = require('ssb-bfe')
const { where, author, type, toPromise } = require('ssb-db2/operators')
const { toPromise } = require('ssb-db2/operators')

function createSSBServer() {
return SecretStack({ appKey: caps.shs })
Expand All @@ -23,7 +21,7 @@ function createSSBServer() {
.use(require('ssb-bendy-butt'))
.use(require('ssb-db2/compat/ebt'))
.use(require('ssb-meta-feeds'))
.use(require('ssb-index-feed-writer'))
.use(require('ssb-index-feeds'))
.use(require('../'))
}

Expand Down Expand Up @@ -71,7 +69,7 @@ const simpleContent = { text: 'hello world', type: 'post' }
tape('butt2 performance', async (t) => {
// falsify to test butt2
if (true) { t.end(); return }

alice.ebt.registerFormat(butt2Methods)
bob.ebt.registerFormat(butt2Methods)

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 bendyButt = require('ssb-bendy-butt/format')
const ebtFormatFrom = require('./base')

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 buttwoo = require('ssb-buttwoo/format')
const ebtFormatFrom = require('./base')

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 classic = require('ssb-classic/format')
const ebtFormatFrom = require('./base')

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
},
}
63 changes: 16 additions & 47 deletions formats/indexed.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,25 @@
const pify = require('promisify-4loc')
const ref = require('ssb-ref')
const { QL0 } = require('ssb-subset-ql')
const indexed = require('ssb-index-feeds/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)
if (Array.isArray(msgTuple) && msgTuple.length === 2) {
const [msgVal, payload] = msgTuple
sbot.db.addTransaction([msgVal], [payload], cb)
} else {
cb(new Error('Invalid index feed message tuple received by ssb-ebt'))
}
},
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) => {
getAtSequence(sbot, pair, cb) {
sbot.getAtSequence([pair.id, pair.sequence], (err, indexMsg) => {
if (err) return cb(err)

cb(null, [msgVal, indexedMsg.value])
sbot.db.get(indexMsg.value.content.indexed, (err, payload) => {
if (err) return cb(err)
cb(null, [indexMsg.value, payload])
})
})
},
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