feat: M3 peer gossip protocol
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
This commit is contained in:
@@ -26,27 +26,18 @@ observations it now holds.`,
|
||||
if dryRun {
|
||||
return dryRunReconcile(kdb)
|
||||
}
|
||||
return reconcile(kdb)
|
||||
created, linked, err := watch.Reconcile(kdb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("reconciled: entries rebuilt, %d threads created, %d observations linked\n", created, linked)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&dryRun, "dry-run", false, "report drift without writing")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func reconcile(kdb *db.KnoxDB) error {
|
||||
before, after, err := kdb.RebuildEntriesFromObservations()
|
||||
if err != nil {
|
||||
return fmt.Errorf("rebuild entries: %w", err)
|
||||
}
|
||||
threader := watch.NewAutoThreader(kdb)
|
||||
created, linked, err := threader.AutoThread()
|
||||
if err != nil {
|
||||
return fmt.Errorf("auto-thread: %w", err)
|
||||
}
|
||||
fmt.Printf("reconciled: entries %d -> %d, %d threads created, %d observations linked\n", before, after, created, linked)
|
||||
return nil
|
||||
}
|
||||
|
||||
func dryRunReconcile(kdb *db.KnoxDB) error {
|
||||
// Ground truth from the log (computed in a throwaway way via a count of
|
||||
// what rebuild would produce) vs the current materialized cache.
|
||||
|
||||
Reference in New Issue
Block a user