mirror of https://codeberg.org/pzp/pzp-gc.git
Rename to pzp and upgrade modules
This commit is contained in:
parent
9075f983d8
commit
b0157ed984
|
@ -1,25 +0,0 @@
|
||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [18.x, 20.x]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
- run: npm install
|
|
||||||
- run: npm test
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
matrix:
|
||||||
|
NODE_VERSION:
|
||||||
|
- 18
|
||||||
|
- 20
|
||||||
|
|
||||||
|
steps:
|
||||||
|
test:
|
||||||
|
when:
|
||||||
|
event: [push]
|
||||||
|
image: node:${NODE_VERSION}
|
||||||
|
commands:
|
||||||
|
- npm install
|
||||||
|
- npm test
|
|
@ -1,9 +1,7 @@
|
||||||
**Work in progress**
|
# pzp-gc
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
We're not on npm yet. In your package.json, include this as
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
"ppppp-gc": "github:staltz/ppppp-gc"
|
npm install pzp-gc
|
||||||
```
|
```
|
||||||
|
|
149
lib/index.js
149
lib/index.js
|
@ -2,9 +2,20 @@
|
||||||
const multicb = require('multicb')
|
const multicb = require('multicb')
|
||||||
const makeDebug = require('debug')
|
const makeDebug = require('debug')
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const p = (fn) => (...args) => {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
// @ts-ignore
|
||||||
|
fn(...args, (err, val) => {
|
||||||
|
if (err) return rej(err)
|
||||||
|
return res(val)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {ReturnType<import('ppppp-db').init>} PPPPPDB
|
* @typedef {ReturnType<import('pzp-db').init>} pzpDB
|
||||||
* @typedef {ReturnType<import('ppppp-goals').init>} PPPPPGoal
|
* @typedef {ReturnType<import('pzp-goals').init>} pzpGoal
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* gc: {
|
* gc: {
|
||||||
* maxLogBytes: number
|
* maxLogBytes: number
|
||||||
|
@ -23,12 +34,12 @@ const makeDebug = require('debug')
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {{ db: PPPPPDB, goals: PPPPPGoal }} peer
|
* @param {{ db: pzpDB, goals: pzpGoal }} peer
|
||||||
* @param {Config} config
|
* @param {Config} config
|
||||||
*/
|
*/
|
||||||
function initGC(peer, config) {
|
function initGC(peer, config) {
|
||||||
// State
|
// State
|
||||||
const debug = makeDebug('ppppp:gc')
|
const debug = makeDebug('pzp:gc')
|
||||||
let stopMonitoringLogSize = /** @type {CallableFunction | null} */ (null)
|
let stopMonitoringLogSize = /** @type {CallableFunction | null} */ (null)
|
||||||
let hasCleanupScheduled = false
|
let hasCleanupScheduled = false
|
||||||
|
|
||||||
|
@ -47,77 +58,79 @@ function initGC(peer, config) {
|
||||||
/**
|
/**
|
||||||
* Deletes messages that don't correspond to any goal.
|
* Deletes messages that don't correspond to any goal.
|
||||||
* @private
|
* @private
|
||||||
* @param {CB<void>} cb
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
function cleanup(cb) {
|
async function cleanup() {
|
||||||
debug('Cleanup started')
|
return new Promise(async (res, rej) => {
|
||||||
const startTime = Date.now()
|
debug('Cleanup started')
|
||||||
const done = multicb({ pluck: 1 })
|
const startTime = Date.now()
|
||||||
|
const done = multicb({ pluck: 1 })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} errExplanation
|
* @param {string} errExplanation
|
||||||
*/
|
*/
|
||||||
function makeRecCB(errExplanation) {
|
function makeRecCB(errExplanation) {
|
||||||
const cb = done()
|
const cb = done()
|
||||||
return (/**@type {Error=}*/ err) => {
|
return (/**@type {Error=}*/ err) => {
|
||||||
if (err) debug('%s: %s', errExplanation, flattenCauseChain(err))
|
if (err) debug('%s: %s', errExplanation, flattenCauseChain(err))
|
||||||
cb()
|
cb()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let waiting = false
|
let waiting = false
|
||||||
for (const rec of peer.db.records()) {
|
for await (const rec of peer.db.records()) {
|
||||||
if (!rec.msg) continue
|
if (!rec.msg) continue
|
||||||
const { id: msgID, msg } = rec
|
const { id: msgID, msg } = rec
|
||||||
const [purpose, details] = peer.goals.getMsgPurpose(msgID, msg)
|
const [purpose, details] = await p(peer.goals.getMsgPurpose)(msgID, msg)
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
case 'goal': {
|
case 'goal': {
|
||||||
continue // don't cleanup
|
continue // don't cleanup
|
||||||
}
|
}
|
||||||
case 'none': {
|
case 'none': {
|
||||||
const recCB = makeRecCB('Failed to delete msg when cleaning up')
|
const recCB = makeRecCB('Failed to delete msg when cleaning up')
|
||||||
debug('Deleting msg %s with purpose=none', msgID)
|
debug('Deleting msg %s with purpose=none', msgID)
|
||||||
peer.db.del(msgID, recCB)
|
|
||||||
waiting = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case 'ghost': {
|
|
||||||
const { tangleID, span } = details
|
|
||||||
const recCB = makeRecCB('Failed to delete ghost msg when cleaning up')
|
|
||||||
// TODO: Could one msg be a ghostable in MANY tangles? Or just one?
|
|
||||||
debug('Deleting and ghosting msg %s with purpose=ghost', msgID)
|
|
||||||
peer.db.ghosts.add({ tangleID, msgID, span }, (err) => {
|
|
||||||
if (err) return recCB(err)
|
|
||||||
peer.db.del(msgID, recCB)
|
peer.db.del(msgID, recCB)
|
||||||
})
|
waiting = true
|
||||||
waiting = true
|
continue
|
||||||
continue
|
}
|
||||||
}
|
case 'ghost': {
|
||||||
case 'trail': {
|
const { tangleID, span } = details
|
||||||
if (!msg.data) continue // it's already erased
|
const recCB = makeRecCB('Failed to delete ghost msg when cleaning up')
|
||||||
const recCB = makeRecCB('Failed to erase trail msg when cleaning up')
|
// TODO: Could one msg be a ghostable in MANY tangles? Or just one?
|
||||||
debug('Erasing msg %s with purpose=trail', msgID)
|
debug('Deleting and ghosting msg %s with purpose=ghost', msgID)
|
||||||
peer.db.erase(msgID, recCB)
|
peer.db.ghosts.add({ tangleID, msgID, span }, (err) => {
|
||||||
waiting = true
|
if (err) return recCB(err)
|
||||||
continue
|
peer.db.del(msgID, recCB)
|
||||||
}
|
})
|
||||||
default: {
|
waiting = true
|
||||||
cb(new Error('Unreachable'))
|
continue
|
||||||
return
|
}
|
||||||
|
case 'trail': {
|
||||||
|
if (!msg.data) continue // it's already erased
|
||||||
|
const recCB = makeRecCB('Failed to erase trail msg when cleaning up')
|
||||||
|
debug('Erasing msg %s with purpose=trail', msgID)
|
||||||
|
peer.db.erase(msgID, recCB)
|
||||||
|
waiting = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
rej(new Error('Unreachable'))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (waiting) done(whenEnded)
|
if (waiting) done(whenEnded)
|
||||||
else whenEnded()
|
else whenEnded()
|
||||||
|
|
||||||
/** @param {Error=} err */
|
/** @param {Error=} err */
|
||||||
function whenEnded(err) {
|
function whenEnded(err) {
|
||||||
const duration = Date.now() - startTime
|
const duration = Date.now() - startTime
|
||||||
if (err) debug('Cleanup ended with an error %s', err.message ?? err)
|
if (err) debug('Cleanup ended with an error %s', err.message ?? err)
|
||||||
else debug('Cleanup completed in %sms', duration)
|
else debug('Cleanup completed in %sms', duration)
|
||||||
cb()
|
res()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,7 +216,7 @@ function initGC(peer, config) {
|
||||||
if (needsCompaction) reportCompactionNeed(percentDeleted, stats)
|
if (needsCompaction) reportCompactionNeed(percentDeleted, stats)
|
||||||
hasCleanupScheduled = true
|
hasCleanupScheduled = true
|
||||||
if (needsCleanup) {
|
if (needsCleanup) {
|
||||||
cleanup(() => {
|
cleanup().finally(() => {
|
||||||
compact(() => {
|
compact(() => {
|
||||||
hasCleanupScheduled = false
|
hasCleanupScheduled = false
|
||||||
})
|
})
|
||||||
|
@ -253,7 +266,7 @@ function initGC(peer, config) {
|
||||||
*/
|
*/
|
||||||
function forceImmediately(cb) {
|
function forceImmediately(cb) {
|
||||||
debug('Force clean and compact immediately')
|
debug('Force clean and compact immediately')
|
||||||
cleanup(() => {
|
cleanup().finally(() => {
|
||||||
compact(cb)
|
compact(cb)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
22
package.json
22
package.json
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "ppppp-gc",
|
"name": "pzp-gc",
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"description": "PPPPP garbage collector",
|
"description": "PZP garbage collector",
|
||||||
"author": "Andre Staltz <contact@staltz.com>",
|
"author": "Andre Staltz <contact@staltz.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://github.com/staltz/ppppp-gc",
|
"homepage": "https://codeberg.org/pzp/pzp-gc",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git@github.com:staltz/ppppp-gc.git"
|
"url": "git@codeberg.org:pzp/pzp-gc.git"
|
||||||
},
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -31,12 +31,12 @@
|
||||||
"@types/debug": "4.1.9",
|
"@types/debug": "4.1.9",
|
||||||
"bs58": "^5.0.0",
|
"bs58": "^5.0.0",
|
||||||
"c8": "7",
|
"c8": "7",
|
||||||
"ppppp-caps": "github:staltz/ppppp-caps#93fa810b9a40b78aef4872d4c2a8412cccb52929",
|
"pzp-caps": "^1.0.0",
|
||||||
"ppppp-db": "github:staltz/ppppp-db#667b33779d98aff12a9b0cd2d7c80469a95cd04e",
|
"pzp-db": "^1.0.1",
|
||||||
"ppppp-dict": "github:staltz/ppppp-dict#6f0ff4e3383a8c18b766949f6db9b51460ecb640",
|
"pzp-dict": "^1.0.0",
|
||||||
"ppppp-goals": "github:staltz/ppppp-goals#f862c2de624649906a4375711f3813db3b94a2ca",
|
"pzp-goals": "^1.0.0",
|
||||||
"ppppp-keypair": "github:staltz/ppppp-keypair#61ef4420578f450dc2cc7b1efc1c5a691a871c74",
|
"pzp-keypair": "^1.0.0",
|
||||||
"ppppp-set": "github:staltz/ppppp-set#8983ba29f03db95a76b4bd9a55aa4392b350fdbb",
|
"pzp-set": "^1.0.0",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^2.6.2",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
"rimraf": "^4.4.0",
|
"rimraf": "^4.4.0",
|
||||||
|
|
|
@ -51,7 +51,7 @@ test('Dict ghosts', async (t) => {
|
||||||
let msgID3
|
let msgID3
|
||||||
let msgID4
|
let msgID4
|
||||||
let msgID5
|
let msgID5
|
||||||
for (const rec of alice.db.records()) {
|
for await (const rec of alice.db.records()) {
|
||||||
if (rec.msg.metadata.dataSize === 0) mootID = rec.id
|
if (rec.msg.metadata.dataSize === 0) mootID = rec.id
|
||||||
if (rec.msg.data?.update?.name === 'alice') msgID1 = rec.id
|
if (rec.msg.data?.update?.name === 'alice') msgID1 = rec.id
|
||||||
if (rec.msg.data?.update?.age === 24) msgID2 = rec.id
|
if (rec.msg.data?.update?.age === 24) msgID2 = rec.id
|
||||||
|
@ -60,18 +60,22 @@ test('Dict ghosts', async (t) => {
|
||||||
if (rec.msg.data?.update?.name === 'ALICE') msgID5 = rec.id
|
if (rec.msg.data?.update?.name === 'ALICE') msgID5 = rec.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
// Assert situation before GC
|
// Assert situation before GC
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getFields([...alice.db.msgs()]),
|
getFields(msgs),
|
||||||
['alice', 24, 'Alice', 25, 'ALICE'],
|
['alice', 24, 'Alice', 25, 'ALICE'],
|
||||||
'has all dict msgs'
|
'has all dict msgs'
|
||||||
)
|
)
|
||||||
assert.ok(isErased(alice.db.get(mootID)), 'moot by def erased')
|
assert.ok(isErased(await p(alice.db.get)(mootID)), 'moot by def erased')
|
||||||
assert.ok(isPresent(alice.db.get(msgID1)), 'msg1 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID1)), 'msg1 exists')
|
||||||
assert.ok(isPresent(alice.db.get(msgID2)), 'msg2 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID2)), 'msg2 exists')
|
||||||
assert.ok(isPresent(alice.db.get(msgID3)), 'msg3 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID3)), 'msg3 exists')
|
||||||
assert.ok(isPresent(alice.db.get(msgID4)), 'msg4 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID4)), 'msg4 exists')
|
||||||
assert.ok(isPresent(alice.db.get(msgID5)), 'msg5 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID5)), 'msg5 exists')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
await p(alice.db.log.stats)(),
|
await p(alice.db.log.stats)(),
|
||||||
|
@ -84,9 +88,13 @@ test('Dict ghosts', async (t) => {
|
||||||
alice.goals.set(dictID, 'dict')
|
alice.goals.set(dictID, 'dict')
|
||||||
await p(alice.gc.forceImmediately)()
|
await p(alice.gc.forceImmediately)()
|
||||||
|
|
||||||
|
const msgs2 = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs2.push(msg)
|
||||||
|
}
|
||||||
// Assert situation after GC
|
// Assert situation after GC
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getFields([...alice.db.msgs()]),
|
getFields(msgs2),
|
||||||
[25, 'ALICE'],
|
[25, 'ALICE'],
|
||||||
'alice has only field root msgs'
|
'alice has only field root msgs'
|
||||||
)
|
)
|
||||||
|
@ -97,12 +105,12 @@ test('Dict ghosts', async (t) => {
|
||||||
'log stats after'
|
'log stats after'
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.ok(isErased(alice.db.get(mootID)), 'moot by def erased')
|
assert.ok(isErased(await p(alice.db.get)(mootID)), 'moot by def erased')
|
||||||
assert.ok(isDeleted(alice.db.get(msgID1)), 'msg1 deleted')
|
assert.ok(isDeleted(await p(alice.db.get)(msgID1)), 'msg1 deleted')
|
||||||
assert.ok(isDeleted(alice.db.get(msgID2)), 'msg2 deleted') // ghost!
|
assert.ok(isDeleted(await p(alice.db.get)(msgID2)), 'msg2 deleted') // ghost!
|
||||||
assert.ok(isErased(alice.db.get(msgID3)), 'msg3 erased')
|
assert.ok(isErased(await p(alice.db.get)(msgID3)), 'msg3 erased')
|
||||||
assert.ok(isPresent(alice.db.get(msgID4)), 'msg4 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID4)), 'msg4 exists')
|
||||||
assert.ok(isPresent(alice.db.get(msgID5)), 'msg5 exists')
|
assert.ok(isPresent(await p(alice.db.get)(msgID5)), 'msg5 exists')
|
||||||
|
|
||||||
assert.deepEqual(alice.db.ghosts.get(dictID), [msgID2])
|
assert.deepEqual(alice.db.ghosts.get(dictID), [msgID2])
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,12 @@ test('Feed decay', async (t) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A0', 'A1', 'A2', 'A3', 'A4'],
|
['A0', 'A1', 'A2', 'A3', 'A4'],
|
||||||
'alice has the whole feed'
|
'alice has the whole feed'
|
||||||
)
|
)
|
||||||
|
@ -39,8 +43,12 @@ test('Feed decay', async (t) => {
|
||||||
|
|
||||||
await p(alice.gc.forceImmediately)()
|
await p(alice.gc.forceImmediately)()
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A2', 'A3', 'A4'],
|
['A2', 'A3', 'A4'],
|
||||||
'alice has only latest 3 msgs in the feed'
|
'alice has only latest 3 msgs in the feed'
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,8 +28,12 @@ test('Feed holes', async (t) => {
|
||||||
posts.push(rec.id)
|
posts.push(rec.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
|
['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
|
||||||
'alice has the whole feed'
|
'alice has the whole feed'
|
||||||
)
|
)
|
||||||
|
@ -40,8 +44,12 @@ test('Feed holes', async (t) => {
|
||||||
await p(alice.db.erase)(posts[6]) // vital as trail from A7
|
await p(alice.db.erase)(posts[6]) // vital as trail from A7
|
||||||
assert('alice deleted the middle part of the feed')
|
assert('alice deleted the middle part of the feed')
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A0', 'A1', 'A2', /* */ 'A7', 'A8', 'A9'],
|
['A0', 'A1', 'A2', /* */ 'A7', 'A8', 'A9'],
|
||||||
'alice has the beginning and the end of the feed'
|
'alice has the beginning and the end of the feed'
|
||||||
)
|
)
|
||||||
|
@ -63,8 +71,12 @@ test('Feed holes', async (t) => {
|
||||||
await p(alice.gc.forceImmediately)()
|
await p(alice.gc.forceImmediately)()
|
||||||
assert.deepEqual(calledErase, [posts[2]], 'erased A2')
|
assert.deepEqual(calledErase, [posts[2]], 'erased A2')
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
[/* */ 'A7', 'A8', 'A9'],
|
[/* */ 'A7', 'A8', 'A9'],
|
||||||
'alice has only the end of the feed'
|
'alice has only the end of the feed'
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const test = require('node:test')
|
const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const p = require('node:util').promisify
|
const p = require('node:util').promisify
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('pzp-keypair')
|
||||||
const { createPeer } = require('./util')
|
const { createPeer } = require('./util')
|
||||||
|
|
||||||
const bobKeypair = Keypair.generate('ed25519', 'bob')
|
const bobKeypair = Keypair.generate('ed25519', 'bob')
|
||||||
|
@ -53,8 +53,12 @@ test('Orphan weave msgs', async (t) => {
|
||||||
tangles: [threadRoot.id],
|
tangles: [threadRoot.id],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['B0', 'A1', 'C1'],
|
['B0', 'A1', 'C1'],
|
||||||
'alice has the full thread'
|
'alice has the full thread'
|
||||||
)
|
)
|
||||||
|
@ -62,8 +66,12 @@ test('Orphan weave msgs', async (t) => {
|
||||||
await p(alice.db.del)(threadRoot.id)
|
await p(alice.db.del)(threadRoot.id)
|
||||||
assert('alice deleted the root')
|
assert('alice deleted the root')
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A1', 'C1'],
|
['A1', 'C1'],
|
||||||
'alice has only thread replies'
|
'alice has only thread replies'
|
||||||
)
|
)
|
||||||
|
@ -76,8 +84,12 @@ test('Orphan weave msgs', async (t) => {
|
||||||
|
|
||||||
await p(alice.gc.forceImmediately)()
|
await p(alice.gc.forceImmediately)()
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A1'],
|
['A1'],
|
||||||
'alice does not have the thread, except her own reply'
|
'alice does not have the thread, except her own reply'
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,8 +25,12 @@ test('Cleanup is scheduled automatically', async (t) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A0', 'A1', 'A2', 'A3', 'A4'],
|
['A0', 'A1', 'A2', 'A3', 'A4'],
|
||||||
'alice has the whole feed'
|
'alice has the whole feed'
|
||||||
)
|
)
|
||||||
|
@ -39,8 +43,12 @@ test('Cleanup is scheduled automatically', async (t) => {
|
||||||
alice.gc.start(4 * 1024) // 4kB, approximately 8 messages
|
alice.gc.start(4 * 1024) // 4kB, approximately 8 messages
|
||||||
await p(setTimeout)(3000)
|
await p(setTimeout)(3000)
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A2', 'A3', 'A4'],
|
['A2', 'A3', 'A4'],
|
||||||
'alice has only latest 3 msgs in the feed'
|
'alice has only latest 3 msgs in the feed'
|
||||||
)
|
)
|
||||||
|
@ -68,8 +76,12 @@ test('Compaction is scheduled automatically', async (t) => {
|
||||||
msgIDs.push(rec.id)
|
msgIDs.push(rec.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A', 'B', 'C', 'D', 'E'],
|
['A', 'B', 'C', 'D', 'E'],
|
||||||
'alice has 5 messages'
|
'alice has 5 messages'
|
||||||
)
|
)
|
||||||
|
@ -79,8 +91,12 @@ test('Compaction is scheduled automatically', async (t) => {
|
||||||
await p(alice.db.del)(msgIDs[3])
|
await p(alice.db.del)(msgIDs[3])
|
||||||
await p(alice.db.del)(msgIDs[4])
|
await p(alice.db.del)(msgIDs[4])
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['C'],
|
['C'],
|
||||||
'alice has 1 message before compaction'
|
'alice has 1 message before compaction'
|
||||||
)
|
)
|
||||||
|
@ -95,8 +111,12 @@ test('Compaction is scheduled automatically', async (t) => {
|
||||||
alice.gc.start(6 * 1024) // 6kB, approximately 12 messages
|
alice.gc.start(6 * 1024) // 6kB, approximately 12 messages
|
||||||
await p(setTimeout)(3000)
|
await p(setTimeout)(3000)
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['C'],
|
['C'],
|
||||||
'alice has 1 message after compaction'
|
'alice has 1 message after compaction'
|
||||||
)
|
)
|
||||||
|
@ -129,8 +149,12 @@ test('start() will automatically stop()', async (t) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A0', 'A1', 'A2', 'A3', 'A4'],
|
['A0', 'A1', 'A2', 'A3', 'A4'],
|
||||||
'alice has the whole feed'
|
'alice has the whole feed'
|
||||||
)
|
)
|
||||||
|
@ -138,8 +162,12 @@ test('start() will automatically stop()', async (t) => {
|
||||||
alice.gc.start(4 * 1024) // 4kB, approximately 8 messages
|
alice.gc.start(4 * 1024) // 4kB, approximately 8 messages
|
||||||
await p(setTimeout)(3000)
|
await p(setTimeout)(3000)
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
for await (const msg of alice.db.msgs()) {
|
||||||
|
msgs.push(msg)
|
||||||
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
getTexts([...alice.db.msgs()]),
|
getTexts(msgs),
|
||||||
['A2', 'A3', 'A4'],
|
['A2', 'A3', 'A4'],
|
||||||
'alice has only latest 3 msgs in the feed'
|
'alice has only latest 3 msgs in the feed'
|
||||||
)
|
)
|
||||||
|
|
14
test/util.js
14
test/util.js
|
@ -1,15 +1,15 @@
|
||||||
const OS = require('node:os')
|
const OS = require('node:os')
|
||||||
const Path = require('node:path')
|
const Path = require('node:path')
|
||||||
const rimraf = require('rimraf')
|
const rimraf = require('rimraf')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('pzp-caps')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('pzp-keypair')
|
||||||
|
|
||||||
function createPeer(config) {
|
function createPeer(config) {
|
||||||
if (config.name) {
|
if (config.name) {
|
||||||
const name = config.name
|
const name = config.name
|
||||||
const tmp = OS.tmpdir()
|
const tmp = OS.tmpdir()
|
||||||
config.global ??= {}
|
config.global ??= {}
|
||||||
config.global.path ??= Path.join(tmp, `ppppp-gc-${name}-${Date.now()}`)
|
config.global.path ??= Path.join(tmp, `pzp-gc-${name}-${Date.now()}`)
|
||||||
config.global.keypair ??= Keypair.generate('ed25519', name)
|
config.global.keypair ??= Keypair.generate('ed25519', name)
|
||||||
delete config.name
|
delete config.name
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,10 @@ function createPeer(config) {
|
||||||
return require('secret-stack/bare')()
|
return require('secret-stack/bare')()
|
||||||
.use(require('secret-stack/plugins/net'))
|
.use(require('secret-stack/plugins/net'))
|
||||||
.use(require('secret-handshake-ext/secret-stack'))
|
.use(require('secret-handshake-ext/secret-stack'))
|
||||||
.use(require('ppppp-db'))
|
.use(require('pzp-db'))
|
||||||
.use(require('ppppp-dict'))
|
.use(require('pzp-dict'))
|
||||||
.use(require('ppppp-set'))
|
.use(require('pzp-set'))
|
||||||
.use(require('ppppp-goals'))
|
.use(require('pzp-goals'))
|
||||||
.use(require('ssb-box'))
|
.use(require('ssb-box'))
|
||||||
.use(require('../lib'))
|
.use(require('../lib'))
|
||||||
.call(null, {
|
.call(null, {
|
||||||
|
|
Loading…
Reference in New Issue