fix: honor read_from_replicas for sharded pubsub subscriptions in ClusterPubSub - #4204
fix: honor read_from_replicas for sharded pubsub subscriptions in ClusterPubSub#4204Brumbelow wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit c2f60ee. Configure here.
|
Hey @Brumbelow, thank you for your contribution! You're right that the server side allows this — Redis forwards shard messages to all nodes in the shard, so a client may subscribe to a shard channel on the slot's primary or on any of its replicas, and we already send Before we take this toward merge there is a design question to settle on our side: those two options are documented as read-command routing knobs (and Two points are blockers regardless of that decision:
Please keep this as a draft in the meantime. I'll follow up on #3266 for the operational scenario behind the request, which is what decides whether we do this at all and whether it should be an explicit opt-in. |
…slot A slot missing from slots_cache came out of the async nodes manager as a bare KeyError, so the reconcile deferral in reinitialize_shard_subscriptions never fired and ssubscribe did not match the sync error type. The uncovered-slot tests now resolve through the real NodesManager.get_node_from_slot instead of a canned side effect, and iterate the uncovered channel first so a reconcile pass that aborts instead of deferring can no longer pass them.
Subscribes two same-slot channels with read_from_replicas enabled so the round-robin places one on the shard's replica, then checks SPUBLISH reaches both subscriptions.
|
Thanks @petyaslavova , both blockers are pushed and addressed.
Will keep as draft until you all tell me otherwise. Let me know if I can help! |

Description of change
Fixes #3266
ClusterPubSubroutes every sharded subscription to the slot's primary:ssubscribe, thesunsubscribefallback, andreinitialize_shard_subscriptionsresolve nodes viaget_node_from_key(), which ignoresread_from_replicasandload_balancing_strategy— unlike regular pub/sub node selection inClusterPubSub.execute_command, which honors both.Shard-channel resolution now goes through the same
nodes_manager.get_node_from_slot(slot, read_from_replicas, load_balancing_strategy)in the sync and async clients. Since a shard subscription may now live on a replica, the keep-vs-migrate decisions (slot-migration reconciliation and the lazy re-route inssubscribe) check whether the tracked node still serves the channel's slot instead of comparing against a fresh pick, so subscriptions don't bounce between shard siblings on topology refreshes.With the default configuration (
read_from_replicas=False, no load balancing strategy) behavior is unchanged: subscriptions resolve to and strictly follow the slot primary, andSlotNotCoveredErroris still raised for uncovered slots.Pull Request check-list
Note
Medium Risk
Touches cluster pub/sub routing and migration/reconcile paths in both sync and async clients; behavior changes only when replica reads or load balancing is enabled, but mistakes could drop or duplicate shard subscriptions during failover.
Overview
Fixes #3266 by aligning shard pub/sub node selection in sync and async
ClusterPubSubwith regular cluster routing:ssubscribe,sunsubscribefallback, andreinitialize_shard_subscriptionsnow usenodes_manager.get_node_from_slot(slot, read_from_replicas, load_balancing_strategy)instead ofget_node_from_key()(primary-only).A new
_eligible_subscription_nodeshelper defines which nodes may hold a subscription for a slot (replicas included only when replica reads or load balancing is enabled). Keep-vs-migrate logic no longer compares the tracked node to a fresh balancer pick; it skips migration when the tracked node still serves the slot, avoiding churn between primary and replica on re-subscribe or topology refresh.sunsubscribewithout a reverse-index entry scans eligible slot nodes for the pubsub that actually holds the channel.Default config (
read_from_replicas=False) behavior is unchanged. Tests are updated for the new resolution path and extended for replica routing, sibling stability, and unsubscribe fallback.Reviewed by Cursor Bugbot for commit c2f60ee. Bugbot is set up for automated code reviews on this repo. Configure here.