8c054094a1
Refs #1 - peers table (peer_id, addr, cursor, last_handshake) - watch serves HTTP API: GET /v1/ping (knowledge vector), GET /v1/log?node=&after= (cursor-paged pull), POST /v1/obs/batch - anti-entropy sweep (Run): ping, pull what we lack, push own obs; echo suppressed by node_id ownership; reconcile-on-pull - config via KNOX_PEERS / KNOX_PEER_ADDR; knox gossip status - db: GossipObservation wire type, PushObservations, ObservationsAfter, KnowledgeVector, peer upsert/list - integration tests: bidirectional convergence + idempotency
50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/david/knox/internal/db"
|
|
"github.com/david/knox/internal/watch"
|
|
)
|
|
|
|
// NewGossipCmd exposes peer status/diff for the gossip protocol.
|
|
func NewGossipCmd(kdb *db.KnoxDB) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "gossip",
|
|
Short: "Inspect peer-to-peer observation sync",
|
|
}
|
|
cmd.AddCommand(
|
|
&cobra.Command{
|
|
Use: "status",
|
|
Short: "Show known peers and knowledge vectors",
|
|
RunE: func(c *cobra.Command, args []string) error {
|
|
peers, err := kdb.ListPeers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
vector, err := kdb.KnowledgeVector()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("node_id: %s\n", kdb.NodeID())
|
|
fmt.Printf("peers (static: %d configured):\n", len(watch.PeerAddrs()))
|
|
for _, p := range peers {
|
|
fmt.Printf(" %-24s %-28s last=%s vector=%d\n", p.PeerID, p.Addr, p.LastHandshake, p.Cursor)
|
|
}
|
|
if len(peers) == 0 {
|
|
fmt.Println(" (none — set KNOX_PEERS to sync with other nodes)")
|
|
}
|
|
fmt.Println("knowledge vector (node_id -> max hcl):")
|
|
for nid, hcl := range vector {
|
|
if nid == kdb.NodeID() {
|
|
continue
|
|
}
|
|
fmt.Printf(" %-24s -> %d\n", nid, hcl)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
)
|
|
return cmd
|
|
} |