From 01087908a74de4edde434e344c693655bb84ce7c Mon Sep 17 00:00:00 2001 From: Mauve Signweaver Date: Thu, 19 Mar 2026 17:30:32 -0400 Subject: [PATCH 1/2] feat: core.purge with rocksdb storage --- index.js | 1 - lib/core.js | 11 +++++++++++ test/all.js | 2 +- test/helpers/index.js | 6 ++++++ test/purge.js | 38 +++++++++++++++++++------------------- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/index.js b/index.js index c3e4dc831..0d9874d5e 100644 --- a/index.js +++ b/index.js @@ -867,7 +867,6 @@ class Hypercore extends EventEmitter { } async purge() { - await this._closeAllSessions(null) await this.core.purge() } diff --git a/lib/core.js b/lib/core.js index b7c4d9522..b2c14918b 100644 --- a/lib/core.js +++ b/lib/core.js @@ -909,6 +909,17 @@ module.exports = class Core { for (const s of weakSessions) s.close().catch(noop) } + async purge() { + if (this.opened === false) await this.opening + const tx = this.storage.write() + tx.deleteTreeNodeRange(0, -1) + tx.deleteBlockRange(0, -1) + this.bitfield.clear(tx) + await tx.flush() + await this.closeAllSessions() + await this.close() + } + async _close() { if (this.opened === false) await this.opening if (this.hasSession() === true) throw new Error('Cannot close while sessions are open') diff --git a/test/all.js b/test/all.js index f696b5d1d..841350805 100644 --- a/test/all.js +++ b/test/all.js @@ -26,7 +26,7 @@ async function runTests() { await import('./move-to.js') await import('./mutex.js') await import('./preload.js') - // await import('./purge.js') // todo: implement purge + await import('./purge.js') await import('./push.js') await import('./remote-bitfield.js') await import('./remote-length.js') diff --git a/test/helpers/index.js b/test/helpers/index.js index 2fc2a8b09..586fa1fb5 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -109,3 +109,9 @@ exports.replicateDebugStream = function replicate(a, b, t, opts = {}) { exports.eventFlush = async function eventFlush() { await new Promise((resolve) => setImmediate(resolve)) } + +exports.toArray = async function toArray(stream) { + const all = [] + for await (const data of stream) all.push(data) + return all +} diff --git a/test/purge.js b/test/purge.js index e15547c67..101b33b90 100644 --- a/test/purge.js +++ b/test/purge.js @@ -1,33 +1,33 @@ const test = require('brittle') -const fs = require('fs') -const Path = require('path') -const Hypercore = require('..') +const Hypercore = require('../') +const { createStorage, toArray } = require('./helpers') test('basic purge', async function (t) { const dir = await t.tmp() - const core = new Hypercore(dir) + const storage = await createStorage(t, dir) + const core = new Hypercore(storage) + await core.append(['a', 'b', 'c']) - const oplogLoc = Path.join(dir, 'oplog') - const treeLoc = Path.join(dir, 'tree') - const bitfieldLoc = Path.join(dir, 'bitfield') - const dataLoc = Path.join(dir, 'data') + // Sanity check for core having data + t.is(core.length, 3) - t.is(fs.existsSync(oplogLoc), true) - t.is(fs.existsSync(treeLoc), true) - t.is(fs.existsSync(bitfieldLoc), true) - t.is(fs.existsSync(dataLoc), true) - t.is(fs.readdirSync(dir).length, 4) // Sanity check + const discoveryKey = core.discoveryKey await core.purge() - t.is(core.closed, true) - t.is(fs.existsSync(oplogLoc), false) - t.is(fs.existsSync(treeLoc), false) - t.is(fs.existsSync(bitfieldLoc), false) - t.is(fs.existsSync(dataLoc), false) - t.is(fs.readdirSync(dir).length, 0) // Nothing remains + const reopenedStorage = await createStorage(t, dir) + const coreStorage = await reopenedStorage.resumeCore(discoveryKey) + + const allBlocks = await toArray(coreStorage.createBlockStream()) + t.is(allBlocks.length, 0) + + const allTreeNodes = await toArray(coreStorage.createTreeNodeStream()) + t.is(allTreeNodes.length, 0) + + const allBitfieldPages = await toArray(coreStorage.createBitfieldStream()) + t.is(allBitfieldPages.length, 0) }) test('purge closes all sessions', async function (t) { From 4de478e3802268c64ff4911159ba04b315c8f686 Mon Sep 17 00:00:00 2001 From: Mauve Signweaver Date: Mon, 23 Mar 2026 10:52:03 -0400 Subject: [PATCH 2/2] fix: teardown storage after purge test --- test/purge.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/purge.js b/test/purge.js index 101b33b90..36344e8c2 100644 --- a/test/purge.js +++ b/test/purge.js @@ -19,6 +19,7 @@ test('basic purge', async function (t) { const reopenedStorage = await createStorage(t, dir) const coreStorage = await reopenedStorage.resumeCore(discoveryKey) + t.teardown(() => reopenedStorage.close()) const allBlocks = await toArray(coreStorage.createBlockStream()) t.is(allBlocks.length, 0)