133 lines
4.9 KiB
JavaScript
133 lines
4.9 KiB
JavaScript
import { runTransactionalLifecycleHooks } from './bare-os-lifecycle-manager.js'
|
|
/**
|
|
* Host lifecycle: when Corestore / Hyperswarm expose `suspend`/`resume`, wire them into
|
|
* `ctx.bareOsInvokeSuspendHooks` / `ctx.bareOsInvokeResumeHooks` (mobile sleep, etc.).
|
|
*/
|
|
|
|
/** @type {{ store: unknown, swarm: unknown } | null} */
|
|
let pendingPair = null
|
|
|
|
/**
|
|
* Called once from main() with live instances; hooks install on first guest ctx.
|
|
* @param {unknown} store
|
|
* @param {unknown} swarm
|
|
*/
|
|
export function bareOsRegisterCorestoreSuspendResumeHooks(store, swarm) {
|
|
pendingPair = { store, swarm }
|
|
}
|
|
|
|
/**
|
|
* Corestore 7.12+ no longer flushes on `suspend()`. Flush open sessions first
|
|
* so in-memory tree/blocks hit storage before the RocksDB handle sleeps.
|
|
* @param {unknown} store
|
|
*/
|
|
async function flushCorestoreSessions(store) {
|
|
if (!store || typeof store !== 'object') return
|
|
const sessions = /** @type {{ sessions?: Iterable<unknown> }} */ (store)
|
|
.sessions
|
|
if (!sessions || typeof sessions[Symbol.iterator] !== 'function') return
|
|
/** @type {Promise<unknown>[]} */
|
|
const pending = []
|
|
for (const sess of sessions) {
|
|
if (!sess || typeof sess !== 'object') continue
|
|
const flush = /** @type {{ flush?: () => unknown }} */ (sess).flush
|
|
if (typeof flush === 'function')
|
|
pending.push(Promise.resolve(flush.call(sess)))
|
|
}
|
|
if (pending.length) await Promise.all(pending)
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} target
|
|
* @param {string} label
|
|
*/
|
|
async function callSuspendResume(target, label) {
|
|
if (!target || typeof target !== 'object') return
|
|
if (label === 'suspend') await flushCorestoreSessions(target)
|
|
const o = /** @type {{ suspend?: () => unknown, resume?: () => unknown }} */ (
|
|
target
|
|
)
|
|
const fn = label === 'suspend' ? o.suspend : o.resume
|
|
if (typeof fn !== 'function') return
|
|
await Promise.resolve(fn.call(target))
|
|
}
|
|
|
|
/**
|
|
* @param {{ bareOsRegisterSuspendHook: (fn: () => void | Promise<void>) => unknown, bareOsRegisterResumeHook: (fn: () => void | Promise<void>) => unknown }} ctx
|
|
*/
|
|
export function bareOsInstallCorestoreSuspendResumeHooks(ctx) {
|
|
if (!pendingPair) return
|
|
const { store, swarm } = pendingPair
|
|
ctx.bareOsRegisterSuspendHook(async () => {
|
|
const rep = await runTransactionalLifecycleHooks([
|
|
{
|
|
name: 'corestore.suspend',
|
|
run: () => callSuspendResume(store, 'suspend')
|
|
},
|
|
{ name: 'swarm.suspend', run: () => callSuspendResume(swarm, 'suspend') }
|
|
])
|
|
if (!rep.ok) throw new Error('bare-os suspend hook transaction failed')
|
|
})
|
|
ctx.bareOsRegisterResumeHook(async () => {
|
|
const rep = await runTransactionalLifecycleHooks([
|
|
{ name: 'swarm.resume', run: () => callSuspendResume(swarm, 'resume') },
|
|
{
|
|
name: 'corestore.resume',
|
|
run: () => callSuspendResume(store, 'resume')
|
|
}
|
|
])
|
|
if (!rep.ok) throw new Error('bare-os resume hook transaction failed')
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Non-secret operator hint for integrating **`corestore-snapshot`** on the host.
|
|
* @param {unknown} store
|
|
*/
|
|
export function bareOsCorestoreSnapshotOperatorHint(store) {
|
|
const env = globalThis.process?.env
|
|
const snapRaw = String(env?.BARE_OS_CORESTORE_SNAPSHOT_JSON || '').trim()
|
|
const statsRaw = String(env?.BARE_OS_CORESTORE_STATS_JSON || '').trim()
|
|
let snapshotKeyCount = null
|
|
let statsNamespaceCount = null
|
|
if (snapRaw) {
|
|
try {
|
|
const s = JSON.parse(snapRaw)
|
|
if (s && typeof s === 'object') {
|
|
if (Array.isArray(s.handles)) snapshotKeyCount = s.handles.length
|
|
else if (Array.isArray(s.keys)) snapshotKeyCount = s.keys.length
|
|
}
|
|
} catch {
|
|
snapshotKeyCount = -1
|
|
}
|
|
}
|
|
if (statsRaw) {
|
|
try {
|
|
const st = JSON.parse(statsRaw)
|
|
if (st && typeof st === 'object' && Array.isArray(st.namespaces))
|
|
statsNamespaceCount = st.namespaces.length
|
|
} catch {
|
|
statsNamespaceCount = -1
|
|
}
|
|
}
|
|
return {
|
|
schema: 4,
|
|
note: 'Wire the holepunch corestore-snapshot package on the host; guests receive this descriptor only. Schema 4 adds recommendedWorkflow; schema 3 adds merge hints when BARE_OS_CORESTORE_SNAPSHOT_JSON and BARE_OS_CORESTORE_STATS_JSON parse.',
|
|
corestoreSnapshotPackage: 'corestore-snapshot',
|
|
recommendedWorkflow: [
|
|
'Run corestore-snapshot (holepunchto/corestore-snapshot) on the host store.',
|
|
'Export JSON into BARE_OS_CORESTORE_SNAPSHOT_JSON and pair BARE_OS_CORESTORE_STATS_JSON for operator diff UX.',
|
|
'Use replication_operator_sketch.corestoreSnapshotUxHint counts in /proc and disk.os RPC.'
|
|
],
|
|
hasLiveStore: !!(store && typeof store === 'object'),
|
|
guestSuspendResume: 'ENOTSUP',
|
|
guestSuspendResumeNote:
|
|
'Kernel guests do not call store.suspend() directly; booter wires hooks when the runtime exposes suspend/resume.',
|
|
corestoreSnapshotEnvPresent: !!snapRaw,
|
|
corestoreStatsEnvPresent: !!statsRaw,
|
|
snapshotManifestKeyCount: snapshotKeyCount,
|
|
statsNamespacesCount: statsNamespaceCount,
|
|
atMs: Date.now()
|
|
}
|
|
}
|