118 lines
3.3 KiB
JavaScript
118 lines
3.3 KiB
JavaScript
/**
|
|
* Linked peer warm pull: replicate Corestore A → B, open remote bee by dbKeyHex,
|
|
* query metric points without re-scraping.
|
|
*/
|
|
import test from 'brittle'
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
import Corestore from 'corestore'
|
|
import { PearDataModel } from '../server/db/model.js'
|
|
import { MetricStore } from '../server/services/store.js'
|
|
import { openDb, closeDb } from '../server/db/index.js'
|
|
import { openRemoteDb, closeRemoteDbs, queryRemoteMetricPoints } from '../server/db/remote.js'
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
const TMP = path.join(__dirname, '..', 'tmp-swarm-pull-test')
|
|
|
|
function replicatePair(a, b) {
|
|
const s1 = a.replicate(true)
|
|
const s2 = b.replicate(false)
|
|
s1.pipe(s2).pipe(s1)
|
|
return () => {
|
|
try {
|
|
s1.destroy()
|
|
} catch {
|
|
// ignore
|
|
}
|
|
try {
|
|
s2.destroy()
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
}
|
|
|
|
test('linked peer pulls warm points over corestore replicate', async (t) => {
|
|
fs.rmSync(TMP, { recursive: true, force: true })
|
|
const dirA = path.join(TMP, 'a')
|
|
const dirB = path.join(TMP, 'b-local')
|
|
|
|
const storeA = new Corestore(path.join(dirA, 'corestore'))
|
|
await storeA.ready()
|
|
const coreA = storeA.get({ name: 'peardata-meta' })
|
|
const modelA = new PearDataModel(coreA, { autoUpdate: true })
|
|
await modelA.ready()
|
|
|
|
const now = Date.now()
|
|
await modelA.putMetricPoints([
|
|
{
|
|
chart: 'system.cpu',
|
|
context: 'system.cpu',
|
|
ts: now - 90_000,
|
|
values: { user: 15, system: 5, nice: 0, iowait: 0, irq: 0, softirq: 0, idle: 80 },
|
|
tier: 1,
|
|
},
|
|
{
|
|
chart: 'system.cpu',
|
|
context: 'system.cpu',
|
|
ts: now - 30_000,
|
|
values: { user: 25, system: 5, nice: 0, iowait: 0, irq: 0, softirq: 0, idle: 70 },
|
|
tier: 1,
|
|
},
|
|
])
|
|
|
|
const dbKeyHex = modelA.publicKeyHex
|
|
|
|
// B: local agent HyperDB + open A's core by key, then replicate
|
|
process.env.PEARDATA_DATA_DIR = dirB
|
|
delete process.env.PEARDATA_HYPERDB
|
|
await closeDb().catch(() => {})
|
|
await closeRemoteDbs().catch(() => {})
|
|
const localB = await openDb()
|
|
t.ok(localB)
|
|
|
|
const remote = await openRemoteDb(dbKeyHex)
|
|
t.ok(remote)
|
|
|
|
const storeB = (await import('../server/db/index.js')).getCorestore()
|
|
const stop = replicatePair(storeA, storeB)
|
|
|
|
// wait for remote core to download blocks
|
|
const deadline = Date.now() + 10_000
|
|
let rows = []
|
|
while (Date.now() < deadline) {
|
|
rows = await queryRemoteMetricPoints({
|
|
chart: 'system.cpu',
|
|
afterMs: now - 180_000,
|
|
beforeMs: now + 1000,
|
|
tier: 1,
|
|
limit: 100,
|
|
})
|
|
if (rows.length >= 2) break
|
|
await new Promise((r) => setTimeout(r, 100))
|
|
}
|
|
|
|
t.ok(rows.length >= 2, `expected warm rows, got ${rows.length}`)
|
|
|
|
// MetricStore query should surface hyperdb-remote when memory empty
|
|
const mem = new MetricStore()
|
|
const q = await mem.query({
|
|
chart: 'system.cpu',
|
|
after: Math.floor((now - 180_000) / 1000),
|
|
before: Math.floor(now / 1000),
|
|
points: 60,
|
|
tier: 1,
|
|
})
|
|
t.ok(q.source === 'hyperdb-remote' || q.source === 'hyperdb-warm')
|
|
t.ok(q.data.length >= 2)
|
|
|
|
stop()
|
|
await closeRemoteDbs()
|
|
await closeDb()
|
|
await modelA.close().catch(() => {})
|
|
await storeA.close().catch(() => {})
|
|
fs.rmSync(TMP, { recursive: true, force: true })
|
|
delete process.env.PEARDATA_DATA_DIR
|
|
})
|