Repository navigation
Whole-keyspace ownership and whole-command forwarding for a plugin keyspace #886
Description
Activity
- addedenhancementNew feature or requestNew feature or requestarea:replicationReplication, cluster sync, peer connectionsReplication, cluster sync, peer connectionsfeature:plugin-substratePlugin substrate primitives; Redis endpoint and job queue are the consumers.Plugin substrate primitives; Redis endpoint and job queue are the consumers.
on Sep 21, 2026 From the planning review (Cursor Grok leg), adopted: forwarding needs a session model, not just a transport, and it is a precondition for calling this a product.
Two things have no owner today:
- The principal.
AUTH aliceon a non-owner, then a forwardedGET, runs on the owner with an empty user (every read authorization fails) or with the plugin's connection identity (alice's permissions never apply). Tracked with the authorization contract in Specify the authorization contract for protocol plugins: a read-only principal can write through an adapter harper#2726. - Session state: selected database, queued
MULTIbuffer, pub/sub mode. Keep it on the accepting node and aMULTI/SET/EXECcan run across different nodes. Keep it on the owner and every blocked client and subscriber holds owner-side resources.
One sticky owner-side session per connection is the answer both point to, and it belongs in this issue's acceptance criteria rather than being discovered during implementation.
The review also independently corroborated the home-map correction already recorded above, by a different route: on a non-replicated keyspace a non-owner either 503s, because there is no replicated log for the barrier to wait on, or it lock-arbitrates and then writes locally, which produces a second accepted copy of the same key. That is the invariant this epic exists to protect, so the correction stands on two reviews rather than one.
- The principal.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
The multi-node path for a plugin keyspace: one node owns the whole keyspace, and every other node
forwards entire commands to it. Mandatory before any migration-facing product, because without
it a load-balanced multi-node deployment makes the common Redis uses wrong by construction.
Reuse the operator mechanics, not the home map
An earlier version of this issue recommended generalizing the shipped record-lock home map, on the
observation that a map with exactly one member resolves every key to that node and so is a
whole-keyspace owner. That recommendation was wrong and has been withdrawn.
homeMap()is keyed by database, and its member list governs every table in that database.Forcing it to one member to obtain a Redis owner would therefore also centralize ordinary record
locks for the whole application database onto the Redis owner node: enabling Redis for one
application would silently re-home unrelated table locks. It is also registered only for replicated
databases, its transport interface is a closed method set, and its freshness barrier refuses
non-replicated tables.
What to reuse is the machinery, in a domain of its own: the generation counter, the
homeIncarnationcontinuity datum, the staged-then-activate quiescence sequence, the digestagreement check, and the external-fencing requirement — inside a separately named ownership domain
scoped to the plugin keyspace, leaving the database's own locking topology untouched.
The ownership contract
the lock work's rendezvous hash over key names is the wrong unit here. A later scale-out step must
adopt
CROSSSLOTplus hash tags rather than pretend.that cannot reach the owner fails the command. It does not serve it locally.
only and then writes locally, so it is precedent for the transport but not for the forwarding
semantics this needs.
a correctness bug rather than a degraded mode. The record-lock work reached the same conclusion
independently and recorded it as a decision, not a gap.
Dependencies
The peer-scoped transport in this epic, and the core enlistment and decision primitives from the
parent epic.