OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-did-peer commits / 2702b56

0.2.1: front() waits for a verified head (single-call correctness)
Bug found verifying the bridge repoint: DidPeerRouter.front() returned as soon as a co-owner's front was opened (provide() kicks off replication), but the head is only set once the firehose commit REPLICATES + verifies on 'append'. A single front() call with no retry (a real getRepo request) thus resolved to a head-less front and every read failed until the next call. The co-owned test masked it by polling front() 40x with sleeps. Fix: front() now waits (bounded by timeout) for AT LEAST ONE co-owner to reach a verified head, then serves the freshest among those ready — a slow co-owner never delays serving from a ready one. The wait lives in front() (freshest-of-ready), NOT in _ensureFront (which would serialize on each co-owner's ready and break the freshest-by-rev co-owned test). Suite green: commitops + router + co-owned. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2702b569d0ab6e85999fcf3a9e78e7cfa4e4cd99
by plankatron <fleeky@gmail.com> · 2026-07-23T22:58:24.000Z

Changed files (2) +13 -2

lib/did-peer.js +12 -1
……@@ -530,7 +530,18 @@ export class DidPeerRouter {
530530 if (!this._byDid.has(did) || this._byDid.get(did).size === 0) await this._waitForDid(did, timeout || 20000)
531531 const entries = this._byDid.get(did) || new Map()
532532 await Promise.all([...entries.keys()].map((fh) => this._ensureFront(did, fh).catch(() => null)))
533 const best = this._freshestFront(did)
533 // A front is opened once provide() kicks off replication, but its head is only set once the firehose
534 // commit REPLICATES + verifies (event-driven, on 'append'). For a single front() call (no retry — a
535 // real getRepo request), wait for AT LEAST ONE co-owner to reach a verified head, then serve the
536 // freshest among those ready. A slow co-owner never delays serving from a ready one (freshest-of-ready).
537 let best = this._freshestFront(did)
538 if (!best) {
539 const end = Date.now() + (timeout || 20000)
540 while (!best && Date.now() < end) {
541 await new Promise((r) => setTimeout(r, 100))
542 best = this._freshestFront(did)
543 }
544 }
534545 if (!best) throw new Error(`DidPeerRouter: no frontable co-owner for ${did}`)
535546 return best
536547 }
package.json +1 -1
……@@ -1,6 +1,6 @@
11{
22 "name": "atproto-did-peer",
3 "version": "0.2.0",
3 "version": "0.2.1",
44 "description": "Keyless, direction-free P2P reader/seeder for an atproto DID's repo+firehose Hypercores: announce-push discovery + event-driven head reconciliation + a keyless read surface. The shared primitive beneath atproto-bridge, atproto-relay and favela (extracted from atproto-bridge did-peer.js).",
55 "type": "module",
66 "main": "index.js",