Updates
Release rolling / release (push) Failing after 36s

This commit is contained in:
Raven Scott
2026-07-31 03:30:34 -04:00
parent 7a9a28062d
commit cd3d99fd59
25 changed files with 2833 additions and 421 deletions
+160 -70
View File
@@ -3,6 +3,7 @@
/**
* Mesh region registry (ADR-0007).
* Autobase multi-writer log + Hyperbee view of regions and spatial cells.
* Supports open-membership (optimistic) mode for the experimental global mesh.
*/
const path = require('path')
@@ -18,6 +19,9 @@ const { encodeKey, decodeKey } = require('./invite')
const CELL = 512 // blocks per spatial index cell
/** @type {Map<string, MeshRegistry>} */
const openMeshStores = new Map()
function ensureDir(dir) {
fs.mkdirSync(dir, { recursive: true })
}
@@ -56,53 +60,6 @@ function openView(store) {
})
}
async function applyOps(nodes, view, host) {
for (const node of nodes) {
let op = node.value
if (typeof op === 'string') {
try {
op = JSON.parse(op)
} catch {
continue
}
}
if (!op || typeof op !== 'object') continue
if (op.addWriter) {
const writerKey =
typeof op.addWriter === 'string' ? decodeKeyMaybe(op.addWriter) : b4a.from(op.addWriter)
await host.addWriter(writerKey, { indexer: true })
continue
}
if (op.type === 'enroll' && op.region) {
const r = op.region
const batch = view.batch()
await batch.put('region:' + r.regionId, r)
if (r.bounds) {
for (const cell of cellsCovering(r.bounds)) {
await batch.put('cell:' + cell, r.regionId)
}
}
await batch.flush()
continue
}
if (op.type === 'unenroll' && op.regionId) {
const batch = view.batch()
const existing = await view.get('region:' + op.regionId)
if (existing && existing.value && existing.value.bounds) {
for (const cell of cellsCovering(existing.value.bounds)) {
const cur = await view.get('cell:' + cell)
if (cur && cur.value === op.regionId) await batch.del('cell:' + cell)
}
}
await batch.del('region:' + op.regionId)
await batch.flush()
}
}
}
function decodeKeyMaybe(s) {
try {
return decodeKey(s)
@@ -115,6 +72,67 @@ function decodeKeyMaybe(s) {
}
}
/**
* @param {boolean} openMembership
*/
function makeApply(openMembership) {
return async function applyOps(nodes, view, host) {
for (const node of nodes) {
let op = node.value
if (typeof op === 'string') {
try {
op = JSON.parse(op)
} catch {
continue
}
}
if (!op || typeof op !== 'object') continue
if (openMembership && node.from && node.from.key) {
try {
await host.ackWriter(node.from.key)
await host.addWriter(node.from.key, { indexer: true })
} catch {
/* already admitted or host unavailable */
}
}
if (op.addWriter) {
const writerKey =
typeof op.addWriter === 'string' ? decodeKeyMaybe(op.addWriter) : b4a.from(op.addWriter)
await host.addWriter(writerKey, { indexer: true })
continue
}
if (op.type === 'enroll' && op.region) {
const r = op.region
const batch = view.batch()
await batch.put('region:' + r.regionId, r)
if (r.bounds) {
for (const cell of cellsCovering(r.bounds)) {
await batch.put('cell:' + cell, r.regionId)
}
}
await batch.flush()
continue
}
if (op.type === 'unenroll' && op.regionId) {
const batch = view.batch()
const existing = await view.get('region:' + op.regionId)
if (existing && existing.value && existing.value.bounds) {
for (const cell of cellsCovering(existing.value.bounds)) {
const cur = await view.get('cell:' + cell)
if (cur && cur.value === op.regionId) await batch.del('cell:' + cell)
}
}
await batch.del('region:' + op.regionId)
await batch.flush()
}
}
}
}
async function closeView(view) {
await view.close()
}
@@ -126,6 +144,10 @@ class MeshRegistry extends ReadyResource {
* @param {string} [opts.meshId] local folder id (default from key)
* @param {Buffer|string|null} [opts.bootstrap] mesh key to join; null = create
* @param {string} [opts.name]
* @param {boolean} [opts.openMembership] optimistic open writers (global mesh)
* @param {Buffer} [opts.topic] Hyperswarm topic override
* @param {{ publicKey: Buffer, secretKey: Buffer }} [opts.keyPair] Autobase bootstrap keyPair
* @param {boolean} [opts.global] mark as global mesh in meta
*/
constructor(opts) {
super()
@@ -137,6 +159,12 @@ class MeshRegistry extends ReadyResource {
: null
this.name = opts.name || 'mesh'
this.meshId = opts.meshId || null
this.openMembership = Boolean(opts.openMembership)
this.topic = opts.topic ? b4a.from(opts.topic) : null
this.keyPair = opts.keyPair || null
this.global = Boolean(opts.global)
/** When false, skip Hyperswarm (unit tests that pipe Autobase directly). */
this.enableSwarm = opts.swarm !== false
this.store = null
this.base = null
this.swarm = null
@@ -159,6 +187,30 @@ class MeshRegistry extends ReadyResource {
return this.base && this.base.local && this.base.local.key
}
async _append(value) {
if (this.writable) {
await this.base.append(value)
} else if (this.openMembership) {
await this.base.append(value, { optimistic: true })
} else {
throw new Error('Not a mesh writer')
}
// Don't block forever on DHT convergence — local append is enough for enroll UX
try {
await Promise.race([
this.base.update(),
new Promise((resolve) => setTimeout(resolve, 2500))
])
} catch {
/* ignore update errors; view may still catch up via swarm */
}
}
/** True if this peer can enroll / append (writer or open global mesh). */
get canEnroll() {
return this.writable || this.openMembership
}
async _open() {
const id =
this.meshId ||
@@ -167,15 +219,41 @@ class MeshRegistry extends ReadyResource {
const dir = meshStorePath(this.storageDir, id)
ensureDir(dir)
this.store = new Corestore(path.join(dir, 'corestore'))
this.base = new Autobase(this.store, this.bootstrap, {
const storePath = path.resolve(dir, 'corestore')
const existing = openMeshStores.get(storePath)
if (existing && existing !== this) {
throw new Error(
'Mesh store already open in this process. Close the other mesh before opening again.'
)
}
openMeshStores.set(storePath, this)
this._storePath = storePath
this.store = new Corestore(storePath)
const handlers = {
open: openView,
apply: applyOps,
apply: makeApply(this.openMembership),
close: closeView,
valueEncoding: 'json',
ackInterval: 1000
})
await this.base.ready()
ackInterval: 1000,
optimistic: this.openMembership
}
if (this.keyPair) handlers.keyPair = this.keyPair
try {
this.base = new Autobase(this.store, this.bootstrap, handlers)
await this.base.ready()
} catch (err) {
openMeshStores.delete(storePath)
this._storePath = null
try {
await this.store.close()
} catch {
/* ignore */
}
this.store = null
throw err
}
// Persist mesh meta
const metaPath = path.join(dir, 'meta.json')
@@ -187,6 +265,7 @@ class MeshRegistry extends ReadyResource {
meshId: this.meshId,
key: this.keyZ32,
name: this.name,
global: this.global,
createdAt: Date.now()
},
null,
@@ -196,26 +275,29 @@ class MeshRegistry extends ReadyResource {
}
// Replicate
this.swarm = new Hyperswarm()
this.swarm.on('connection', (conn) => {
this.base.replicate(conn)
})
const topic = crypto.discoveryKey(this.base.key)
this._discovery = this.swarm.join(topic, { server: true, client: true })
await this.swarm.flush()
if (this.enableSwarm) {
this.swarm = new Hyperswarm()
this.swarm.on('connection', (conn) => {
this.base.replicate(conn)
})
const topic = this.topic || crypto.discoveryKey(this.base.key)
this._discovery = this.swarm.join(topic, { server: true, client: true })
await this.swarm.flush()
}
}
/**
* Admit another peer's writer key (must be writable).
* Admit another peer's writer key (must be writable or open-membership).
* @param {Buffer|string} writerKey
*/
async addWriter(writerKey) {
if (!this.writable) throw new Error('Not a mesh writer; cannot addWriter')
if (!this.writable && !this.openMembership) {
throw new Error('Not a mesh writer; cannot addWriter')
}
const key = typeof writerKey === 'string' ? decodeKeyMaybe(writerKey) : b4a.from(writerKey)
await this.base.append({
await this._append({
addWriter: encodeKey(key)
})
await this.base.update()
}
/**
@@ -223,7 +305,9 @@ class MeshRegistry extends ReadyResource {
* @param {object} region RegionRecord
*/
async enroll(region) {
if (!this.writable) throw new Error('Not a mesh writer; cannot enroll')
if (!this.writable && !this.openMembership) {
throw new Error('Not a mesh writer; cannot enroll')
}
if (!region.regionId || !region.worldKey || !region.bounds) {
throw new Error('region requires regionId, worldKey, bounds')
}
@@ -240,16 +324,16 @@ class MeshRegistry extends ReadyResource {
name: region.name || region.regionId,
updatedAt: Date.now()
}
await this.base.append({ type: 'enroll', region: record })
await this.base.update()
await this._append({ type: 'enroll', region: record })
this.emit('enroll', record)
return record
}
async unenroll(regionId) {
if (!this.writable) throw new Error('Not a mesh writer')
await this.base.append({ type: 'unenroll', regionId })
await this.base.update()
if (!this.writable && !this.openMembership) {
throw new Error('Not a mesh writer')
}
await this._append({ type: 'unenroll', regionId })
}
/**
@@ -293,6 +377,12 @@ class MeshRegistry extends ReadyResource {
}
async _close() {
if (this._storePath) {
if (openMeshStores.get(this._storePath) === this) {
openMeshStores.delete(this._storePath)
}
this._storePath = null
}
if (this._discovery) {
try {
await this._discovery.destroy()