import { deepStrictEqual, strictEqual } from 'assert' import { rimraf } from 'rimraf' import { createOrbitDB } from '../src/index.js' import connectPeers from './utils/connect-nodes.js' import waitFor from './utils/wait-for.js' import createHelia from './utils/create-helia.js' import { CID } from 'multiformats/cid' import { base58btc } from 'multiformats/bases/base58' describe('Replicating databases', function () { this.timeout(10000) let ipfs1, ipfs2 let orbitdb1, orbitdb2 before(async () => { ipfs1 = await createHelia({ directory: './ipfs1' }) ipfs2 = await createHelia({ directory: './ipfs2' }) await connectPeers(ipfs1, ipfs2) orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1', directory: './orbitdb1' }) orbitdb2 = await createOrbitDB({ ipfs: ipfs2, id: 'user2', directory: './orbitdb2' }) }) after(async () => { await orbitdb1.stop() await orbitdb2.stop() await ipfs1.blockstore.child.child.child.close() await ipfs2.blockstore.child.child.child.close() await ipfs1.stop() await ipfs2.stop() await rimraf('./orbitdb1') await rimraf('./orbitdb2') await rimraf('./ipfs1') await rimraf('./ipfs2') }) describe('replicating a database', () => { const amount = 128 + 1 const expected = [] for (let i = 0; i < amount; i++) { expected.push('hello' + i) } let db1, db2 before(async () => { db1 = await orbitdb1.open('helloworld', { referencesCount: 0 }) console.time('write') for (let i = 0; i < expected.length; i++) { await db1.add(expected[i]) } console.timeEnd('write') }) afterEach(async () => { await db2.close() }) it('returns all entries in the replicated database', async () => { console.time('replicate') let replicated = false const onJoin = async (peerId, heads) => { replicated = true } const onError = (err) => { console.error(err) } db2 = await orbitdb2.open(db1.address) db2.events.on('join', onJoin) db2.events.on('error', onError) db1.events.on('error', onError) await waitFor(() => replicated, () => true) console.time('query 1') const eventsFromDb2 = [] for await (const event of db2.iterator()) { eventsFromDb2.unshift(event) } console.timeEnd('query 1') console.timeEnd('replicate') deepStrictEqual(eventsFromDb2.map(e => e.value), expected) console.time('query 2') const eventsFromDb1 = [] for await (const event of db1.iterator()) { eventsFromDb1.unshift(event) } console.timeEnd('query 2') deepStrictEqual(eventsFromDb1.map(e => e.value), expected) console.log('events:', amount) }) it('returns all entries in the replicated database after recreating orbitdb/ipfs instances', async () => { console.time('replicate') let replicated = false const onJoin = async (peerId, heads) => { replicated = true } const onError = (err) => { console.error(err) } db2 = await orbitdb2.open(db1.address) db2.events.on('join', onJoin) db2.events.on('error', onError) db1.events.on('error', onError) await waitFor(() => replicated, () => true) console.time('query 1') const eventsFromDb2 = [] for await (const event of db2.iterator()) { eventsFromDb2.unshift(event) } console.timeEnd('query 1') console.timeEnd('replicate') deepStrictEqual(eventsFromDb2.map(e => e.value), expected) await orbitdb1.stop() await orbitdb2.stop() // TODO: Strange issue with ClassicLevel. Causes subsequent Helia // instantiations to error with db closed. Explicitly closing the // nested ClassicLevel db seems to resolve the issue. Requires further // investigation. await ipfs1.blockstore.child.child.child.close() await ipfs2.blockstore.child.child.child.close() await ipfs1.stop() await ipfs2.stop() ipfs1 = await createHelia({ directory: './ipfs1' }) ipfs2 = await createHelia({ directory: './ipfs2' }) await connectPeers(ipfs1, ipfs2) orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1', directory: './orbitdb1' }) orbitdb2 = await createOrbitDB({ ipfs: ipfs2, id: 'user2', directory: './orbitdb2' }) db1 = await orbitdb1.open('helloworld', { referencesCount: 0 }) db2 = await orbitdb2.open(db1.address) console.time('query 2') const eventsFromDb1 = [] for await (const event of db1.iterator()) { eventsFromDb1.unshift(event) } console.timeEnd('query 2') deepStrictEqual(eventsFromDb1.map(e => e.value), expected) console.log('events:', amount) }) it('pins all entries in the replicated database', async () => { const db1 = await orbitdb1.open('helloworld', { referencesCount: 0 }) const hash = await db1.add('hello world') let replicated = false const onJoin = async (peerId, heads) => { replicated = true } const db2 = await orbitdb2.open(db1.address) db2.events.on('join', onJoin) await waitFor(() => replicated, () => true) const cid = CID.parse(hash, base58btc) strictEqual(await ipfs1.pins.isPinned(cid), true) strictEqual(await ipfs2.pins.isPinned(cid), true) }) }) })