state: compute primary routes inside NodeStore snapshot

Add primaries + isPrimary fields to Snapshot. snapshotFromNodes
now elects per-prefix primary advertisers from the current node
set, mirroring routes.PrimaryRoutes.updatePrimaryLocked: skip
exit routes, prefer the previous primary if still a valid
healthy advertiser, fall back to the lowest healthy NodeID, then
to the lowest NodeID overall when all are unhealthy.

Anti-flap memory rides the previous snapshot through applyBatch.
Caller-side coordination is unnecessary; the writer goroutine
serialises every mutation that could change the primary set.

Add NodeStore reader methods (PrimaryFor,
PrimaryRoutesForNode, HANodes, IsNodeHealthy) that mirror the
legacy routes.PrimaryRoutes API on the snapshot. Consumers will
switch in the next commit.

No behaviour change yet — primaries are computed but not read.

Updates #3203
This commit is contained in:
Kristoffer Dalby
2026-04-28 12:44:58 +00:00
parent 6baee3e6c3
commit 3feb307a12
2 changed files with 173 additions and 9 deletions
+1 -1
View File
@@ -150,7 +150,7 @@ func TestSnapshotFromNodes(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
nodes, peersFunc := tt.setupFunc()
snapshot := snapshotFromNodes(nodes, peersFunc)
snapshot := snapshotFromNodes(nodes, peersFunc, nil)
tt.validate(t, nodes, snapshot)
})
}