Skip to content

Cluster: missing slot verification for custom raw-string and custom object commands #1826

Description

@Ankith-Kandala

Describe the bug

In cluster mode, single-key custom raw-string commands and custom object commands (registered via server.Register.NewCommand(...)) are dispatched on the local node without going through cluster slot verification. The node accepts and serves the command regardless of which slot the key belongs to.

In a multi-node cluster this has two effects:

  1. A client sending a custom command to the wrong node never receives a -MOVED <slot> <ip:port> redirection, so it has no way to route correctly.
  2. If the same key is written through two different nodes, both nodes silently accept the write and end up with divergent values for the same key.

Built-in single-key commands like SET/GET against the same key on the same node behave correctly (the non-owning node returns MOVED).

Custom transactions (registered via NewTransactionProc) are not affected. They already go through per-key verification via TxnKeyManager since PR #712. The gap is only on the raw-string (CustomRawStringCmd) and object (CustomObjCmd) dispatch paths.

Steps to reproduce the bug

The stock main/GarnetServer build already registers MYDICTSET/MYDICTGET (custom object) and SETIFPM/SETWPIFPGT/DELIFM (custom raw-string), so no module loading or extra registration is needed.

  1. Start two GarnetServer instances with --cluster.
  2. Form a cluster via CLUSTER MEET and assign slots so node A owns slot 0 and node B owns the rest.
  3. From a RESP client connected to node B (which does NOT own slot 0), send a custom command against a key that hashes to slot 0:
    • MYDICTSET keyOwnedByNodeA field1 value1 -> node B replies +OK.
    • The raw-string path behaves the same way: e.g. SETIFPM keyOwnedByNodeA value prefix is also accepted locally on node B.
  4. Compare with a built-in command against the same key on the same node:
    • SET keyOwnedByNodeA value -> node B replies -MOVED 0 <nodeA-ip:port>, as expected.

Node B silently accepted the custom-command write for a slot it does not own. If a different client follows the correct MOVED redirection to node A and reads the same key, the two nodes hold different values for it.

Expected behavior

Single-key custom raw-string and custom object commands should go through the same verification path as built-in single-key commands:

  • Return -MOVED <slot> <ip:port> when the key's slot is owned by another node.
  • Return -ASK <slot> <ip:port> when the slot is migrating out from this node.
  • Honor the same replica-read rules (e.g. READONLY semantics).

Both dispatch contracts already place the user-supplied key at parseState[0] as a single key, and CommandType (Read vs. ReadModifyWrite/Write) is tracked per-session, so a single-key spec routed through the existing NetworkMultiKeySlotVerify path is enough to close the gap.

Screenshots

No response

Release version

No response

IDE

No response

OS version

No response

Additional context

  • Same class of correctness gap as PR Fix Slot Validation for Custom Proc #712, which introduced the iterative slot verification interface and wired custom transactions through it. This issue is the remaining gap on the other two extension command paths: CustomRawStringCmd and CustomObjCmd.
  • CustomProcedure (non-transactional procedures registered via NewProcedure) is out of scope here. Procedure authors validate keys themselves and the key contract is more open-ended; may be worth a separate follow-up if a centralized path is desirable there too.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions