set ghostSpan
This commit is contained in:
parent
06c41a18a9
commit
bb7383aa6d
33
lib/index.js
33
lib/index.js
|
@ -5,14 +5,16 @@ const makeDebug = require('debug')
|
||||||
* @typedef {ReturnType<import('ppppp-goals').init>} PPPPPGoal
|
* @typedef {ReturnType<import('ppppp-goals').init>} PPPPPGoal
|
||||||
* @typedef {import('ppppp-goals').GoalDSL} GoalDSL
|
* @typedef {import('ppppp-goals').GoalDSL} GoalDSL
|
||||||
* @typedef {ReturnType<import('ppppp-set').init>} PPPPPSet
|
* @typedef {ReturnType<import('ppppp-set').init>} PPPPPSet
|
||||||
|
* @typedef {ReturnType<import('ppppp-dict').init>} PPPPPDict
|
||||||
* @typedef {ReturnType<import('ppppp-sync').init>} PPPPPSync
|
* @typedef {ReturnType<import('ppppp-sync').init>} PPPPPSync
|
||||||
* @typedef {ReturnType<import('ppppp-gc').init>} PPPPPGC
|
* @typedef {ReturnType<import('ppppp-gc').init>} PPPPPGC
|
||||||
* @typedef {`${string}@${GoalDSL}`} Rule
|
* @typedef {`${string}@${GoalDSL}`} Rule
|
||||||
* @typedef {[Array<Rule>, Array<Rule>]} Rules
|
* @typedef {[Array<Rule>, Array<Rule>]} Rules
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* db:PPPPPDB | null,
|
* db: PPPPPDB | null,
|
||||||
* goals: PPPPPGoal | null,
|
* goals: PPPPPGoal | null,
|
||||||
* set: PPPPPSet | null,
|
* set: PPPPPSet | null,
|
||||||
|
* dict: PPPPPDict | null,
|
||||||
* sync: PPPPPSync | null,
|
* sync: PPPPPSync | null,
|
||||||
* gc: PPPPPGC | null,
|
* gc: PPPPPGC | null,
|
||||||
* }} UnknownPeer
|
* }} UnknownPeer
|
||||||
|
@ -83,8 +85,24 @@ function initConductor(peer, config) {
|
||||||
assertGCPlugin(peer)
|
assertGCPlugin(peer)
|
||||||
assertSyncPlugin(peer)
|
assertSyncPlugin(peer)
|
||||||
|
|
||||||
|
const ESTIMATE_TOTAL_GHOST_BYTES = 1024 * 1024 // 1 MB
|
||||||
|
const ESTIMATE_MSG_ID_BYTES = 22 // 22 bytes per msg ID
|
||||||
|
|
||||||
const debug = makeDebug('ppppp:conductor')
|
const debug = makeDebug('ppppp:conductor')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<Rule>} rules
|
||||||
|
*/
|
||||||
|
function countGhostableFeeds(rules) {
|
||||||
|
let count = 2 // 'follow' and 'block' Sets
|
||||||
|
for (const rule of rules) {
|
||||||
|
const [, goalDSL] = parseRule(rule)
|
||||||
|
if (goalDSL === 'dict') count++
|
||||||
|
else if (goalDSL === 'set') count++
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set replication goals for various tangles of an account:
|
* Set replication goals for various tangles of an account:
|
||||||
* - Account tangle
|
* - Account tangle
|
||||||
|
@ -167,10 +185,9 @@ function initConductor(peer, config) {
|
||||||
const [myRules, theirRules] = rules
|
const [myRules, theirRules] = rules
|
||||||
|
|
||||||
// TODO: If goals are too big for maxBytes budget, scale down goals
|
// TODO: If goals are too big for maxBytes budget, scale down goals
|
||||||
// TODO: Figure out ghost spans for dicts and sets
|
|
||||||
|
|
||||||
|
// Set up goals for my account and each account I follow
|
||||||
setupAccountGoals(myID, myRules)
|
setupAccountGoals(myID, myRules)
|
||||||
|
|
||||||
const followedAccounts = peer.set.values('follow')
|
const followedAccounts = peer.set.values('follow')
|
||||||
for (const theirID of followedAccounts) {
|
for (const theirID of followedAccounts) {
|
||||||
setupAccountGoals(theirID, theirRules)
|
setupAccountGoals(theirID, theirRules)
|
||||||
|
@ -189,6 +206,16 @@ function initConductor(peer, config) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Figure out ghost span for each account
|
||||||
|
const totalGhostableFeeds =
|
||||||
|
countGhostableFeeds(myRules) +
|
||||||
|
followedAccounts.length * countGhostableFeeds(theirRules)
|
||||||
|
const TOTAL_GHOSTS = ESTIMATE_TOTAL_GHOST_BYTES / ESTIMATE_MSG_ID_BYTES
|
||||||
|
const ghostSpan = Math.round(TOTAL_GHOSTS / totalGhostableFeeds)
|
||||||
|
peer.set.setGhostSpan(ghostSpan)
|
||||||
|
peer.dict?.setGhostSpan(ghostSpan)
|
||||||
|
|
||||||
|
// Kick off garbage collection and synchronization
|
||||||
peer.gc.start(maxBytes)
|
peer.gc.start(maxBytes)
|
||||||
peer.sync.start()
|
peer.sync.start()
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
"ppppp-caps": "github:staltz/ppppp-caps",
|
"ppppp-caps": "github:staltz/ppppp-caps",
|
||||||
"ppppp-db": "github:staltz/ppppp-db",
|
"ppppp-db": "github:staltz/ppppp-db",
|
||||||
"ppppp-set": "github:staltz/ppppp-set",
|
"ppppp-set": "github:staltz/ppppp-set",
|
||||||
|
"ppppp-dict": "github:staltz/ppppp-dict",
|
||||||
"ppppp-gc": "github:staltz/ppppp-gc",
|
"ppppp-gc": "github:staltz/ppppp-gc",
|
||||||
"ppppp-goals": "github:staltz/ppppp-goals",
|
"ppppp-goals": "github:staltz/ppppp-goals",
|
||||||
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
||||||
|
|
|
@ -350,3 +350,48 @@ test('GC recently-blocked accounts', async (t) => {
|
||||||
await p(bob.close)(true)
|
await p(bob.close)(true)
|
||||||
await p(carol.close)(true)
|
await p(carol.close)(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Set and Dict ghost spans', async (t) => {
|
||||||
|
// Alice
|
||||||
|
const alice = createPeer({ name: 'alice' })
|
||||||
|
await alice.db.loaded()
|
||||||
|
// Alice creates her own account
|
||||||
|
const aliceID = await p(alice.db.account.create)({
|
||||||
|
subdomain: 'account',
|
||||||
|
_nonce: 'alice',
|
||||||
|
})
|
||||||
|
await p(alice.set.load)(aliceID)
|
||||||
|
|
||||||
|
// Bob
|
||||||
|
const bob = createPeer({ name: 'bob' })
|
||||||
|
await bob.db.loaded()
|
||||||
|
// Bob creates his own account
|
||||||
|
const bobID = await p(bob.db.account.create)({
|
||||||
|
subdomain: 'account',
|
||||||
|
_nonce: 'bob',
|
||||||
|
})
|
||||||
|
await p(bob.set.load)(bobID)
|
||||||
|
|
||||||
|
// Carol
|
||||||
|
const carol = createPeer({ name: 'carol' })
|
||||||
|
await carol.db.loaded()
|
||||||
|
// Carol creates her own account
|
||||||
|
const carolID = await p(carol.db.account.create)({
|
||||||
|
subdomain: 'account',
|
||||||
|
_nonce: 'carol',
|
||||||
|
})
|
||||||
|
await p(carol.set.load)(bobID)
|
||||||
|
|
||||||
|
// Alice follows Bob, but not Carol
|
||||||
|
assert(await p(alice.set.add)('follow', bobID), 'alice follows bob')
|
||||||
|
|
||||||
|
alice.conductor.start(aliceID, [['post@all'], ['post@all']], 4_000)
|
||||||
|
bob.conductor.start(bobID, [['post@all'], ['post@all']], 4_000)
|
||||||
|
|
||||||
|
assert.equal(alice.set.getGhostSpan(), 11916, 'alice set ghost span is 2')
|
||||||
|
assert.equal(alice.dict.getGhostSpan(), 11916, 'alice set ghost span is 2')
|
||||||
|
|
||||||
|
await p(alice.close)(true)
|
||||||
|
await p(bob.close)(true)
|
||||||
|
await p(carol.close)(true)
|
||||||
|
})
|
||||||
|
|
|
@ -22,6 +22,7 @@ function createPeer(opts) {
|
||||||
.use(require('ppppp-db'))
|
.use(require('ppppp-db'))
|
||||||
.use(require('ssb-box'))
|
.use(require('ssb-box'))
|
||||||
.use(require('ppppp-set'))
|
.use(require('ppppp-set'))
|
||||||
|
.use(require('ppppp-dict'))
|
||||||
.use(require('ppppp-goals'))
|
.use(require('ppppp-goals'))
|
||||||
.use(require('ppppp-sync'))
|
.use(require('ppppp-sync'))
|
||||||
.use(require('ppppp-gc'))
|
.use(require('ppppp-gc'))
|
||||||
|
|
Loading…
Reference in New Issue