OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-did-peer commits / 6beb0ff

did-peer: fix seed() range/listener leak — single live download, no per-append re-issue
seed() re-ran core.download({start:0,end:-1}) inside a core.on('append', …) listener. end:-1 already downloads all current blocks AND follows future appends (verified: a replica reaches the new length without re-issuing), so the listener was redundant — and harmful: every append minted a NEW, never-destroyed [0,-1] RangeRequest (the Download return value was discarded) plus another append listener. On a re-authoring / ballooning producer (many appends) this accumulated unbounded live ranges + listeners and degraded replication to O(ranges) per tick — the consumer-side amplifier behind the ~100MB/s "never settles" churn. Fix: issue exactly one download({start:0,end:-1}) per core; drop the per-append re-issue. Router test green (both DIDs still replicate + reach a verified head), so seeding/serving behaviour is preserved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6beb0ff2d29a302926829a05426282661de0e22b
by plankatron <fleeky@gmail.com> · 2026-07-17T23:10:14.000Z

Changed files (2) +7 -2

lib/did-peer.js +6 -1
……@@ -66,7 +66,12 @@ export class DidPeer {
6666 // FULL seed so this node can serve the cores to others (download all + follow appends) — this is
6767 // the "each peer seeds" torrent behaviour; a read-only consumer that does NOT want to seed can
6868 // subclass/override, but seeding-by-default is the P2P-native contribution posture.
69 const seed = (core) => { const pull = () => { try { core.download({ start: 0, end: -1 }) } catch {} }; pull(); core.on('append', pull) }
69 // ONE live download range per core: end:-1 downloads all current blocks AND follows future appends
70 // (verified), so a single call is sufficient. The prior form re-ran `core.download({0,-1})` inside a
71 // `core.on('append', …)` listener — every append minted a NEW, never-destroyed [0,-1] RangeRequest and
72 // added another append listener, an UNBOUNDED range/listener leak that a re-authoring or ballooning
73 // producer turned into runaway replication churn (the ~100MB/s "never settles" amplifier).
74 const seed = (core) => { try { core.download({ start: 0, end: -1 }) } catch {} }
7075 seed(this.repo.core); seed(this.seq.core)
7176 // EVENT-DRIVEN: re-derive the served head on every firehose append (local or replicated), and
7277 // re-announce the new length to connected peers. No poll loop.
package.json +1 -1
……@@ -1,6 +1,6 @@
11{
22 "name": "atproto-did-peer",
3 "version": "0.1.0",
3 "version": "0.1.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",