Skip to content

feat: cluster server integration foundation#72

Merged
kacy merged 4 commits intomainfrom
feat/cluster-server-integration
Feb 10, 2026
Merged

feat: cluster server integration foundation#72
kacy merged 4 commits intomainfrom
feat/cluster-server-integration

Conversation

@kacy
Copy link
Copy Markdown
Owner

@kacy kacy commented Feb 10, 2026

summary

wires the ember-cluster crate into the running server. this is the foundation layer — cluster mode flag, gossip networking, working CLUSTER commands, and slot ownership validation with MOVED redirects.

deferred to follow-up PRs: raft consensus, slot migration (ASK redirects), SETSLOT commands, REPLICATE, FAILOVER.

what changed

  • bug fix: cluster_info() was reporting 0 assigned slots because single_node() populates the SlotMap but not node.slots. now derives the count from slot_map.unassigned_count().
  • new file cluster.rs: ClusterCoordinator wrapping cluster crate types with command handlers, slot ownership checks, and gossip UDP networking.
  • CLI flags: --cluster-enabled, --cluster-bootstrap, --cluster-port-offset, --cluster-node-timeout. validates mutual exclusion with --concurrent.
  • cluster commands: INFO, NODES, SLOTS, MYID, MEET, ADDSLOTS, DELSLOTS, FORGET all delegate to the coordinator when cluster is enabled.
  • slot ownership: every single-key data command checks slot ownership and returns MOVED redirects. multi-key commands (DEL, EXISTS, MGET, MSET, RENAME) validate CROSSSLOT.
  • unimplemented commands (SETSLOT, REPLICATE, FAILOVER, etc.) now return "ERR not yet implemented" instead of "cluster support disabled".

what was tested

  • cargo clippy --workspace -- -D warnings — clean
  • cargo test --workspace — all 296 tests pass, no regressions
  • fixed cluster_info_format test to assert cluster_slots_assigned:16384 (was incorrectly asserting 0)

design considerations

  • ClusterCoordinator uses RwLock<ClusterState> for many-reader/rare-writer access and Mutex<GossipEngine> for the gossip tick loop. the read lock is only held briefly during slot checks so it shouldn't be a bottleneck.
  • gossip networking runs two tokio tasks: one for UDP send/recv with tick intervals, another to consume GossipEvents and update cluster state. both are spawned before the accept loop starts.
  • slot checks are done before shard routing (check_cluster_slot returns early with MOVED). when cluster is None, the check is a no-op (zero overhead).
  • check_crossslot is synchronous (no lock needed) since it only computes hash slots from key bytes.

kacy added 4 commits February 9, 2026 19:53
single_node() populates the SlotMap but not node.slots, so
cluster_info() was reporting 0 assigned slots. derive the count
from slot_map.unassigned_count() instead.
introduces ClusterCoordinator wrapping ember-cluster types for
server integration. handles cluster commands (INFO, NODES, SLOTS,
MYID, MEET, ADDSLOTS, DELSLOTS, FORGET), slot ownership checks
with MOVED redirects, and gossip networking via UDP.
adds --cluster-enabled, --cluster-bootstrap, --cluster-port-offset,
and --cluster-node-timeout flags. validates mutual exclusion with
--concurrent mode. creates ClusterCoordinator on startup, spawns
gossip tasks, and passes it into server::run() via ServerContext.
replaces cluster command stubs with dispatch to ClusterCoordinator
when cluster mode is enabled. adds MOVED redirects on all single-key
data commands and CROSSSLOT validation on multi-key commands (DEL,
EXISTS, MGET, MSET, RENAME). unimplemented cluster commands now
return "ERR not yet implemented" instead of "cluster support disabled".
@kacy kacy merged commit 9983bdc into main Feb 10, 2026
6 of 7 checks passed
@kacy kacy deleted the feat/cluster-server-integration branch February 10, 2026 01:14
kacy added a commit that referenced this pull request Feb 11, 2026
* fix(cluster): derive slot counts from slot_map in cluster_info

single_node() populates the SlotMap but not node.slots, so
cluster_info() was reporting 0 assigned slots. derive the count
from slot_map.unassigned_count() instead.

* feat(server): add cluster coordinator module

introduces ClusterCoordinator wrapping ember-cluster types for
server integration. handles cluster commands (INFO, NODES, SLOTS,
MYID, MEET, ADDSLOTS, DELSLOTS, FORGET), slot ownership checks
with MOVED redirects, and gossip networking via UDP.

* feat(server): add cluster CLI flags and server context integration

adds --cluster-enabled, --cluster-bootstrap, --cluster-port-offset,
and --cluster-node-timeout flags. validates mutual exclusion with
--concurrent mode. creates ClusterCoordinator on startup, spawns
gossip tasks, and passes it into server::run() via ServerContext.

* feat(server): wire cluster commands and add slot ownership checks

replaces cluster command stubs with dispatch to ClusterCoordinator
when cluster mode is enabled. adds MOVED redirects on all single-key
data commands and CROSSSLOT validation on multi-key commands (DEL,
EXISTS, MGET, MSET, RENAME). unimplemented cluster commands now
return "ERR not yet implemented" instead of "cluster support disabled".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant