OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-room commits / cf851c7

0.2.20: step markers in serveMembrane — it is awaited during a DID's boot
serveMembrane is awaited inside bootSwarmDevice, so anything slow in it stalls the node. On a phone it stalled with no output at all, leaving "somewhere inside serveMembrane" as the entire diagnosis — the caller's surrounding logs bracket it but nothing inside says which step. Each step is cheap and local on a workstation; the point is that when one is not, the log names it. Timed, because slow and wedged look identical from outside. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cf851c729373f9d0dbd68ff4387960a47fa96630
by plankatron <fleeky@gmail.com> · 2026-08-10T17:10:28.000Z

Changed files (2) +10 -1

lib/serve-membrane.js +9 -0
……@@ -203,8 +203,16 @@ function revTime (rev) {
203203// behavioural change and be verified in place before anything is removed.
204204export async function serveMembrane (device, { corestore, swarm, did, handle, sessions = null, blobs = null, projectRepoCore = true } = {}) {
205205 if (!corestore || !swarm || !did) throw new Error('serveMembrane: corestore, swarm, did required')
206 // Step markers. This function is `await`ed during a DID's boot, so anything slow here stalls the whole
207 // node — and on a phone it stalled with NO output at all, leaving "somewhere inside serveMembrane" as
208 // the entire diagnosis. Each step is cheap and local on a workstation; the point is that when one is
209 // not, the log says WHICH. Timed, because "slow" and "wedged" look identical from outside.
210 const t0 = Date.now()
211 const step = (msg) => { try { console.log(JSON.stringify({ msg: 'membrane: ' + msg, did, ms: Date.now() - t0 })) } catch {} }
206212 const repo = projectRepoCore ? await new RepoStore(corestore, { name: 'membrane-repo:' + did }).ready() : null
213 step(projectRepoCore ? 'repo core ready' : 'repo core SKIPPED (virtual device)')
207214 const seq = await new FirehoseSequencer(corestore.get({ name: 'membrane-firehose:' + did })).ready()
215 step('firehose sequencer ready')
208216 // Project ONLY when the device's __commit__ log has advanced past what the membrane firehose already
209217 // holds. WITHOUT this gate, the caller's sign loop (every signIntervalMs, ~2s) called sync()
210218 // UNCONDITIONALLY, and projectRepo re-put ALL records into the APPEND-ONLY Hyperbee repo core on EVERY
……@@ -399,6 +407,7 @@ export async function serveMembrane (device, { corestore, swarm, did, handle, se
399407 // Both sides must be client:true to punch simultaneously (see peer.js:serve for the full why).
400408 const dKey = swarm.join(swarm.keyPair.publicKey, { server: true, client: true })
401409 const dDid = swarm.join(discoveryTopic(did), { server: true, client: true })
410 step('topics joined — serveMembrane returning (the announce flush is the CALLER\'s to await)')
402411 return {
403412 repo, seq, serverKey, repoKey, firehoseKey, sync,
404413 ready: () => Promise.all([dKey.flushed(), dDid.flushed()]),
package.json +1 -1
……@@ -1,6 +1,6 @@
11{
22 "name": "atproto-room",
3 "version": "0.2.19",
3 "version": "0.2.20",
44 "description": "Attestation-gated, encrypted multi-writer room engine — StateBase (keet-model admission) + Lease + signer + RepoBase + LabelBase/LabelRoom + serve-membrane. Extracted from hyper-proto-peer; consumed by the atproto peer (repo devices) and the co-authored labeler.",
55 "type": "module",
66 "main": "index.js",