From a53b61265c630e64a3171db1508f3ca9aae8b5fb Mon Sep 17 00:00:00 2001 From: pingqiu Date: Sat, 2 May 2026 20:30:54 -0700 Subject: [PATCH] docs(p15): add G9D registration controller consensus --- ...5-g9d-registration-controller-consensus.md | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 sw-block/design/v3-phase-15-g9d-registration-controller-consensus.md diff --git a/sw-block/design/v3-phase-15-g9d-registration-controller-consensus.md b/sw-block/design/v3-phase-15-g9d-registration-controller-consensus.md new file mode 100644 index 000000000..5c6da9043 --- /dev/null +++ b/sw-block/design/v3-phase-15-g9d-registration-controller-consensus.md @@ -0,0 +1,118 @@ +# V3 Phase 15 G9D - Registration / Controller Boundary Consensus + +Date: 2026-05-02 +Status: architect consensus for G9D implementation +Scope: blockmaster registration, heartbeat, inventory, placement, assignment, recovery readiness + +## 1. Core rule + +Registration and heartbeat are observation facts. They do not grant authority, do not make a replica ready, and do not close recovery. + +The controller is the only layer that may turn desired product state plus runtime observations into placement decisions, recovery decisions, and assignment publication requests. + +Publisher emits authority only from controller decisions. Frontends consume readiness projections only after the data-plane facts prove serviceability. + +## 2. Role split + +| Layer | Owns | Must not do | +| --- | --- | --- | +| Desired volume registry | User/product intent: volume exists, size, RF, attach intent | Mint primary, mark replica ready, infer placement from heartbeat | +| Node registration / heartbeat | Node presence, addresses, capacity, labels, local replica inventory | Claim primary, claim replica_ready, close recovery | +| Placement controller | Select candidate nodes/slots from desired state and inventory | Treat observation as data continuity proof | +| Assignment controller / publisher | Publish epoch/endpoint-version authority facts | Bypass recovery/ready facts | +| Recovery feeder | Feed base/WAL and maintain one WAL egress owner per peer | Decide product placement | +| Durable ack / probe | Report progress facts | Create authority directly | +| Frontend | Serve only after frontend_primary_ready | Infer readiness from heartbeat | + +## 3. Fact vocabulary + +### Node registration + +A node registration says: + +- this server exists; +- these addresses and labels are visible; +- these storage pools have capacity; +- these local replica records already exist. + +It is inventory. It is not authority. + +### Desired volume registration + +A desired volume record says: + +- this volume should exist; +- this is the requested size and replication factor. + +It is product intent. It is not placement. + +### Replica inventory + +A replica inventory record says: + +- this node reports a local replica identity; +- the replica has a local durable identity and progress facts; +- the replica may be existing, blank, corrupt, unknown, recovering, or ready-candidate. + +It is evidence for planner/controller. It is not replica_ready. + +### Assignment + +Assignment is epoch/endpoint-version authority published after controller decision. Assignment movement alone does not prove data continuity. + +### Replica ready + +Replica readiness requires recovery/feed/progress facts, including closed recovery window and post-close durable acknowledgement when the replica returned through recovery. + +## 4. Anti-patterns + +The following are design stops: + +1. Heartbeat directly mints primary assignment. +2. Existing local replica inventory directly becomes replica_ready. +3. Blank capacity directly becomes primary. +4. Authority movement alone claims data continuity. +5. Desired volume creation directly starts frontend service. +6. One peer has multiple independent WAL feeders. +7. Delete intent directly drops data-path state without drain/teardown phase. + +## 5. G9D implementation boundary + +G9D first slice may add durable stores for: + +- desired volume intent; +- node registration; +- local replica inventory. + +G9D first slice must not: + +- import `core/adapter`; +- mention `AssignmentInfo`; +- construct `AssignmentFact`; +- publish assignment; +- update engine mode; +- claim replica_ready. + +Tests must pin these boundaries so future controller work consumes inventory through explicit planner seams instead of reintroducing heartbeat-as-authority. + +## 6. Future controller path + +The intended future flow is: + +```text +CreateVolume(volume_id, size, RF) + -> DesiredVolumeStore + +NodeHeartbeat(server_id, pools, local replicas) + -> NodeInventoryStore + +DesiredVolume + NodeInventory + ReplicaInventory + -> PlacementController + -> ReplicaCreate / ReplicaStart / Recover decisions + -> AssignmentController / Publisher + -> blockvolume observes AssignmentFact + -> feeder/recovery proves data-plane facts + -> replica_ready / frontend_ready projections +``` + +This keeps SeaweedFS-style automatic discovery while preserving the V3 anti-pattern boundary: observation facts do not substitute for authority or data-plane proof.