mirror of https://codeberg.org/pzp/pzp-sync.git
82 lines
2.1 KiB
JavaScript
82 lines
2.1 KiB
JavaScript
const { BloomFilter } = require('bloom-filters')
|
|
const FeedV1 = require('ppppp-db/lib/feed-v1')
|
|
|
|
module.exports = function syncAlgorithm(opts = {}) {
|
|
const {
|
|
haveRange,
|
|
wantRange,
|
|
estimateMsgCount,
|
|
yieldMsgsIn,
|
|
commit,
|
|
} = opts
|
|
if (typeof haveRange !== 'function') {
|
|
throw new Error('function haveRange is required')
|
|
}
|
|
if (typeof wantRange !== 'function') {
|
|
throw new Error('function wantRange is required')
|
|
}
|
|
if (typeof estimateMsgCount !== 'function') {
|
|
throw new Error('function estimateMsgCount is required')
|
|
}
|
|
if (typeof yieldMsgsIn !== 'function') {
|
|
throw new Error('function yieldMsgsIn is required')
|
|
}
|
|
if (typeof commit !== 'function') {
|
|
throw new Error('function commit is required')
|
|
}
|
|
|
|
function isEmptyRange(range) {
|
|
const [min, max] = range
|
|
return min > max
|
|
}
|
|
|
|
function countIter(iter) {
|
|
let count = 0
|
|
for (const _ of iter) count++
|
|
return count
|
|
}
|
|
|
|
function betterWantRange(feedId, localHaveRange, remoteHaveRange) {
|
|
if (isEmptyRange(remoteHaveRange)) return [1, 0]
|
|
else return wantRange(feedId, localHaveRange, remoteHaveRange)
|
|
}
|
|
|
|
function bloomFor(feedId, round, range, extraIds = []) {
|
|
const filterSize =
|
|
(isEmptyRange(range) ? 2 : estimateMsgCount(range)) + countIter(extraIds)
|
|
const filter = BloomFilter.create(2 * filterSize, 0.00001)
|
|
if (!isEmptyRange(range)) {
|
|
for (const msg of yieldMsgsIn(feedId, range)) {
|
|
filter.add('' + round + FeedV1.getMsgHash(msg))
|
|
}
|
|
}
|
|
for (const msgId of extraIds) {
|
|
filter.add('' + round + msgId)
|
|
}
|
|
return filter.saveAsJSON()
|
|
}
|
|
|
|
function msgsMissing(feedId, round, range, remoteBloomJSON) {
|
|
if (isEmptyRange(range)) return []
|
|
const remoteFilter = BloomFilter.fromJSON(remoteBloomJSON)
|
|
const missing = []
|
|
for (const msg of yieldMsgsIn(feedId, range)) {
|
|
const msgHash = FeedV1.getMsgHash(msg)
|
|
if (!remoteFilter.has('' + round + msgHash)) {
|
|
missing.push(msgHash)
|
|
}
|
|
}
|
|
return missing
|
|
}
|
|
|
|
return {
|
|
haveRange,
|
|
wantRange: betterWantRange,
|
|
isEmptyRange,
|
|
bloomFor,
|
|
msgsMissing,
|
|
yieldMsgsIn,
|
|
commit,
|
|
}
|
|
}
|