You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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.
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.
Start two GarnetServer instances with --cluster.
Form a cluster via CLUSTER MEET and assign slots so node A owns slot 0 and node B owns the rest.
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.
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.
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:
-MOVED <slot> <ip:port>redirection, so it has no way to route correctly.Built-in single-key commands like
SET/GETagainst the same key on the same node behave correctly (the non-owning node returnsMOVED).Custom transactions (registered via
NewTransactionProc) are not affected. They already go through per-key verification viaTxnKeyManagersince PR #712. The gap is only on the raw-string (CustomRawStringCmd) and object (CustomObjCmd) dispatch paths.Steps to reproduce the bug
The stock
main/GarnetServerbuild already registersMYDICTSET/MYDICTGET(custom object) andSETIFPM/SETWPIFPGT/DELIFM(custom raw-string), so no module loading or extra registration is needed.GarnetServerinstances with--cluster.CLUSTER MEETand assign slots so node A owns slot 0 and node B owns the rest.MYDICTSET keyOwnedByNodeA field1 value1-> node B replies+OK.SETIFPM keyOwnedByNodeA value prefixis also accepted locally on node B.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
MOVEDredirection 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:
-MOVED <slot> <ip:port>when the key's slot is owned by another node.-ASK <slot> <ip:port>when the slot is migrating out from this node.READONLYsemantics).Both dispatch contracts already place the user-supplied key at
parseState[0]as a single key, andCommandType(Readvs.ReadModifyWrite/Write) is tracked per-session, so a single-key spec routed through the existingNetworkMultiKeySlotVerifypath is enough to close the gap.Screenshots
No response
Release version
No response
IDE
No response
OS version
No response
Additional context
CustomRawStringCmdandCustomObjCmd.CustomProcedure(non-transactional procedures registered viaNewProcedure) 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.