Skip to content

Commit efd61ff

Browse files
authored
Handle SPUBLISH as a non key-based command (#182)
1 parent b43a07e commit efd61ff

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

redis/src/cluster_async/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1868,7 +1868,7 @@ where
18681868
// (e.g., sending management command to a different node than the user asked for); instead, raise the error.
18691869
let routable_cmd = cmd.and_then(|cmd| Routable::command(&*cmd));
18701870
if routable_cmd.is_some()
1871-
&& !RoutingInfo::is_key_based_cmd(&routable_cmd.unwrap())
1871+
&& !RoutingInfo::is_key_routing_command(&routable_cmd.unwrap())
18721872
{
18731873
return Err((
18741874
ErrorKind::ClusterConnectionNotFound,

redis/src/cluster_routing.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,10 @@ impl RoutingInfo {
550550
matches!(base_routing(cmd), RouteBy::AllNodes)
551551
}
552552

553-
/// Returns true if the `cmd` is a key-based command.
554-
pub fn is_key_based_cmd(cmd: &[u8]) -> bool {
553+
/// Returns true if the `cmd` is a key-based command that triggers MOVED errors.
554+
/// A key-based command is one that will be accepted only by the slot owner,
555+
/// while other nodes will respond with a MOVED error redirecting to the relevant primary owner.
556+
pub fn is_key_routing_command(cmd: &[u8]) -> bool {
555557
match base_routing(cmd) {
556558
RouteBy::FirstKey
557559
| RouteBy::SecondArg
@@ -560,7 +562,18 @@ impl RoutingInfo {
560562
| RouteBy::SecondArgSlot
561563
| RouteBy::StreamsIndex
562564
| RouteBy::MultiShardNoValues
563-
| RouteBy::MultiShardWithValues => true,
565+
| RouteBy::MultiShardWithValues => {
566+
if matches!(cmd, b"SPUBLISH") {
567+
// SPUBLISH does not return MOVED errors within the slot's shard. This means that even if READONLY wasn't sent to a replica,
568+
// executing SPUBLISH FOO BAR on that replica will succeed. This behavior differs from true key-based commands,
569+
// such as SET FOO BAR, where a non-readonly replica would return a MOVED error if READONLY is off.
570+
// Consequently, SPUBLISH does not meet the requirement of being a command that triggers MOVED errors.
571+
// TODO: remove this when PRIMARY_PREFERRED route for SPUBLISH is added
572+
false
573+
} else {
574+
true
575+
}
576+
}
564577
RouteBy::AllNodes | RouteBy::AllPrimaries | RouteBy::Random | RouteBy::Undefined => {
565578
false
566579
}

0 commit comments

Comments
 (0)