Force-apply topology on reconcile and add a per-cluster sync endpoint (#395) - #400
Force-apply topology on reconcile and add a per-cluster sync endpoint (#395)#400bocharov wants to merge 1 commit into
Conversation
998ffa0 to
3abbe98
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #400 +/- ##
============================================
+ Coverage 43.38% 50.77% +7.39%
============================================
Files 37 45 +8
Lines 2971 4169 +1198
============================================
+ Hits 1289 2117 +828
- Misses 1544 1832 +288
- Partials 138 220 +82
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Addressed the Codecov patch-coverage feedback in 807123c. Added unit tests for the previously-uncovered branches:
|
|
@bocharov Thanks for your contribution, a few comments inline. |
|
@git-hulk thanks for the review — all three addressed in 1e9a79c:
|
|
@bocharov Can help to resolve the CI failure |
…apache#395) Kvrocks cluster nodes do not gossip, so the controller is the sole source of topology and must push a complete, identical view to every node. Today a node can silently diverge at an equal epoch (a dropped push, a partial view, a stale/phantom entry) and never recover: the probe loop only re-pushes SETNODES when a node's epoch lags, and an equal-version SETNODES is no-op'd by the server's version gate; the only prior recovery, CLUSTER RESET, needs an empty DB and so is unusable once a node holds data. Changes: 1. SyncClusterInfo takes a SyncPolicy carrying the SETNODES `force` flag plus a bounded retry-with-backoff. Force makes the topology apply unconditionally, which repairs an equal-epoch drift and clears stale/phantom entries without a data-destroying CLUSTER RESET. 2. The reconcile loop parses cluster_known_nodes and cluster_slots_ok from CLUSTER INFO and force-pushes a node whose peer count or slot coverage disagrees with the desired topology, not only one whose epoch lags. Coverage is compared against the desired covered-slot count, so a cluster mid-scale is not seen as drifted; a node that omits these fields falls back to epoch-only reconcile. The existing "node is ahead" adopt branch is preserved. 3. POST /namespaces/{namespace}/clusters/{cluster}/sync force-pushes the stored topology to every node and reports per-node results — the operator-facing re-push apache#395 asks for. It performs no CLUSTER RESET, so it is safe on a populated cluster. 4. Reject blank/port-less node addresses in CheckNewNodes and Shard.ToSlotsString, so a half-resolved address fails loudly instead of registering a phantom, unreachable node. New unit tests cover the CLUSTER INFO parsing (incl. sentinel/malformed values), the divergence check, address validation, the blank-address guard, the retry/ backoff and force-sync propagation, the probe error paths, and the /sync handler. A behavioral test asserts the reconcile fix by exercising the real probe path.
1e9a79c to
5f36e82
Compare
|
Force-pushed to squash the three commits into one; the tree is byte-identical (no code change). The previous red was a flaky |
Problem
Fixes #395. Kvrocks cluster nodes do not gossip — the controller is the sole source of topology and must push a complete, identical view to every node. Today a node can silently diverge and never recover:
CLUSTERX SETNODESonly when a node's epoch is behind the stored version. A node that has drifted at an equal epoch (a dropped push, a partial view, a stale/phantom node entry) is never repaired.SETNODESis sent withoutforce, so even a re-push at an equal version is a no-op on the server (the version gate rejects a lower version and no-ops an equal one). The only prior recovery wasCLUSTER RESET, which requires an empty DB and so is unusable once a node holds data. Controller's cluster_nodes push silently drops when a data node is unreachable, leaving cluster meta stale forever #395 reports exactly this: divergentcluster_nodessnapshots that never converge, with no operator-facing way to force a re-push.Changes
SyncClusterInfo(ctx, cluster, force)— whenforceis set, send the SETNODESforceflag so the topology applies unconditionally. Because SETNODES replaces the node's whole topology, a forced push also clears stale/phantom entries without aCLUSTER RESETand without data loss. Wrapped in a bounded retry-with-backoff (a push dropped by a transient blip is otherwise not retried until the next tick).Divergence detection at an equal epoch — the reconcile loop parses
cluster_known_nodesandcluster_slots_okfromCLUSTER INFOand force-pushes a node whose peer count or slot coverage disagrees with the desired topology, not only one whose epoch lags. Coverage is compared against the desired covered-slot count (not a hardcoded 16384), so a cluster that is intentionally mid-scale is not seen as drifted; a node that omits these fields falls back to epoch-only reconcile. The existing "node is ahead" adopt branch is preserved.POST /namespaces/{namespace}/clusters/{cluster}/sync— force-push the stored topology to every node and report per-node results. This is the operator-facing re-push Controller's cluster_nodes push silently drops when a data node is unreachable, leaving cluster meta stale forever #395 asks for. It performs noCLUSTER RESET, so it is safe to run on a populated cluster.Reject blank/port-less node addresses in
CheckNewNodes(the create/add-node boundary) andShard.ToSlotsString(serialization), so a half-resolved address fails loudly instead of registering a phantom, unreachable node.Safety
The controller is the single writer of topology (failover routes through it), so "newest complete view wins" holds. Force fires only when a node's version is not greater than the store's; a node legitimately ahead keeps the existing adopt-from-node branch. Verified against Apache Kvrocks 2.16.0 that
CLUSTERX SETNODES <str> <ver> forcebypasses the equal-version no-op.Tests
make testpassing. New unit tests cover theCLUSTER INFOparsing (incl. sentinel/malformed values), the divergence check, address validation, the blank-address guard, and the/synchandler. A behavioral test asserts the reconcile fix by exercising the real probe path.