feat: swarm membership discovery via peer-list gossip
Refs #1 - /v1/ping now advertises the node's known peers (peer_id, addr, name) - Run sweeps static KNOX_PEERS + persisted discovered peers, enqueueing newly-learned addresses for direct sweeps (membership-only relay; no observation relay) - db: ShareablePeers, SwarmPeerAddrs, MergePeer (cursor-preserving discovery upsert), MaxHCLForNode - integration test: a node configured with a single seed discovers and pulls from other swarm members without direct configuration
This commit is contained in:
+11
-4
@@ -125,14 +125,16 @@ a single node the rowid remains monotonic, so the current dedup query
|
||||
|
||||
### 5.1 Transport
|
||||
|
||||
Plain HTTP/JSON on a per-node advertized address (default port `8931`). Nodes
|
||||
discover peers via a static list in `settings` (M3). mDNS/rendezvous is future
|
||||
work.
|
||||
Plain HTTP/JSON on a per-node advertized address (default port `8931`). Peers
|
||||
are seeded from a static list (`KNOX_PEERS`), then the swarm discovers itself:
|
||||
each node advertises its known peer addresses in `/v1/ping`, and every sweep
|
||||
enqueues newly-learned nodes for direct contact (membership gossip — no relay of
|
||||
observations). mDNS/rendezvous is future work.
|
||||
|
||||
Endpoints:
|
||||
|
||||
```
|
||||
GET /v1/ping → { node_id, name, max_hcl }
|
||||
GET /v1/ping → { node_id, name, max_hcl, peers: [{peer_id, addr, name}] }
|
||||
GET /v1/log?after=<seq>&node=<id> → { cursor, rows: [observation...] } # pull
|
||||
POST /v1/obs/batch → body: [observation...]; reply: { accepted n, conflict n } # push
|
||||
GET /v1/diff → divergence summary (M4)
|
||||
@@ -142,6 +144,11 @@ GET /v1/diff → divergence summary (M4)
|
||||
|
||||
- **Knowledge vector:** each node tracks `peer_id → max_hcl consumed`. Anti-entropy
|
||||
is a pull: periodically (and on handshake) query each peer's `/v1/log?after=...`.
|
||||
- **Membership gossip:** `/v1/ping` includes the responding node's known peers
|
||||
(`peer_id`, `addr`, `name`). The caller merges them into its `peers` table and
|
||||
enqueues their addresses for direct sweeps. A new node therefore joins the
|
||||
whole swarm by configuring just one seed peer. Membership flows independently
|
||||
of data — a node never relays another's observations, only its address.
|
||||
- **Push:** on a new local observation, best-effort `POST /v1/obs/batch` to known
|
||||
peers. A node does **not** re-broadcast something it merely received (that peer
|
||||
already has it and will pull from its origin) — this is the echo/loop
|
||||
|
||||
Reference in New Issue
Block a user