Phase C3: ContentDeliveryLayerNode — the per-stream-part overlay node#86
Merged
Conversation
Ports the content-delivery overlay node and its factory from the TS pin, composing the C1/C2 classes with propagation, inspection (C7) and the discovery layer (C4): - ContentDeliveryLayerNode: neighbor list + four contact views fed from discovery-layer events, broadcast with per-publisher duplicate detection, leave-notice handling, RPC server wiring, and TS-parity stop() (leave notices + rpcCommunicator destroy). Plumtree branches are milestone-E scope and omitted. - createContentDeliveryLayerNode: defaults taken from the TS source (neighbor target 4, view size 20, min propagation targets 2, 150-message/10 s buffer, 10 s update interval); components are shared_ptr-wired with documented destruction order. - DhtNodeDiscoveryLayer adapter + DhtNode contact-event re-emission: TS passes a DhtNode wherever a DiscoveryLayerNode is expected (structural typing); DhtNode now re-emits the six PeerManager contact events like TS (second event-emitter base, merged lookup) and the adapter provides the interface nominally. Five real defects found and fixed by the ported tests (all verified with before/after runs per the runtime-evidence methodology): 1. NodeList data race: worker threads iterated lists freed by concurrent replaceAll/add (64-node SetUp SIGSEGV, crash-report stack). All access is now mutex-guarded; NodeAdded/NodeRemoved emit OUTSIDE the lock (their handlers make blocking RPC sends). 2. NodeList ordering parity: the TS NodeList is insertion-ordered and the interleave protocol depends on it (getLast = newest neighbor); the std::map-backed port was id-ordered. Now an insertion-ordered vector; the TS ordering test is ported. 3. Teardown lazy-task lifetime: stop()'s leave-notice coroutines captured remotes whose last references concurrent handlers could drop before the batch ran (the rpc-remote lazy-task trap; teardown SIGSEGV). The batch now pins the remotes. 4. previousMessageRef optionality: TS passes undefined when absent; the port forwarded the proto3 default instance, violating the DuplicateMessageDetector invariant for (0,0) refs. Now optional through the chain. 5. Synchronous propagation deadlock: sendToNeighbor ran blockingWait inside the RPC delivery path — under broadcast fan-out nodes blocked sending to each other in cycles and propagation stalled (0/3 timeouts at 64 nodes). Propagation sends are now Task-returning scope tasks (3/3 after); ProxyClient keeps its synchronous result API via an awaitable collect variant. Tests ported: unit/ContentDeliveryLayerNode.test.ts (+ loopback suppression cases), integration/ContentDeliveryLayerNode-Layer1Node .test.ts and its -Latencies variant (shared fixture, 50 ms fixed latency), integration/Propagation.test.ts (64 nodes instead of TS's 256 — the C++ simulator's per-node cost makes 256 a ~16 min run, beyond CI budget; scale-up is a documented follow-up), and the full unit/NodeList.test.ts (14 cases). Local: trackerless-network 83/83 with clean process exit, streamr-dht 181/181, full-tree build green, both package lints rc=0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports the content-delivery overlay node and its factory from the TS pin — the class that composes the C1/C2 classes (temporary connections, handshaking, neighbor finding/updating) with propagation, inspection (C7) and the discovery layer (C4) into the actual per-stream-part node. The test porting flushed out five real defects, each diagnosed with runtime evidence (crash-report stacks, rate comparisons) and verified fixed.
What's ported
ContentDeliveryLayerNode— neighbor list + the four contact views (nearby/random/ring-left/ring-right) fed from discovery-layer events, broadcast with per-publisher duplicate detection, leave-notice handling with view eviction, temporary-connection and content-delivery RPC server wiring,suppressOwnMessageLoopback, and TS-paritystop(). Plumtree branches are milestone-E scope and omitted.createContentDeliveryLayerNode— defaults taken from the TS source (neighbor target 4, view size 20, min propagation targets 2, 150-message/10 s buffer, 10 s update interval); explicit shared-pointer ownership graph in place of TS garbage collection, with documented destruction order.DhtNodeDiscoveryLayer+DhtNodecontact-event re-emission — TS passes aDhtNodewherever aDiscoveryLayerNodeis expected (structural typing).DhtNodenow re-emits the six PeerManager contact events as its own, exactly like TS (second event-emitter base with merged lookup), and the adapter provides the interface nominally. C6'sNetworkStackwill reuse it.Five defects found by the ported tests
NodeListdata race — worker threads iterated lists being mutated concurrently (64-node SetUp segfault; crash-report stack throughgetValuesOfIncludedKeys). All access mutex-guarded;NodeAdded/NodeRemovedemit outside the lock (their handlers make blocking RPC sends).NodeListordering parity — TS'sMapis insertion-ordered and the interleave protocol depends on it (getLast= newest neighbor to hand over); thestd::mapport was id-ordered. Now an insertion-ordered vector; TS's ordering test ported.stop()'s leave-notice coroutines captured remotes whose last references concurrent handlers could drop before the batch ran (the documented rpc-remote lazy-task trap). The batch pins the remotes; verified 0/3 → 8/8 on the crashing fixture.previousMessageRefoptionality — TS passesundefinedwhen absent; the port forwarded the proto3 default instance, tripping theDuplicateMessageDetectorinvariant for (0, 0) refs. Optional through the whole chain now.sendToNeighborranblockingWaitinside the RPC delivery path, so under broadcast fan-out nodes blocked sending to each other in cycles and propagation stalled (0/3 timeouts at 64 nodes).Propagationsends are now Task-returning bounded scope tasks (3/3 after);ProxyClientkeeps its synchronous result-reporting API through a new awaitable collect variant.Tests (all ported from the pin)
unit/ContentDeliveryLayerNode.test.ts(incl. loopback-suppression cases)ContentDeliveryLayerNodeTest(9 tests)integration/ContentDeliveryLayerNode-Layer1Node.test.tsContentDeliveryLayerNodeLayer1Test(single node / 4 nodes + bidirectionality / 64 nodes) over real DhtNodes + simulatorintegration/...-Latencies.test.tsintegration/Propagation.test.tsPropagationScaleTestat 64 nodes (TS runs 256; the C++ simulator's per-node cost makes that a ~16 min run, beyond CI budget — scale-up documented as follow-up)unit/NodeList.test.ts(14 cases)NodeListTest(stub → full port, incl. insertion order)Results (local, arm64 mac)
trackerless-network 83/83 with verified clean process exit, streamr-dht 181/181 (regression for the
DhtNodeevent additions), full-tree build green, both package lints and the repo-wide lint rc=0.Remaining milestone-C phases after this: C5 (
ContentDeliveryManager+ proxy server side), C6 (NetworkStack/NetworkNode), C8 (full-node end-to-end + TS interop).🤖 Generated with Claude Code