Skip to content

feat: support cluster topology discovery via CLUSTER SHARDS command - #4266

Open
bchrobot wants to merge 4 commits into
redis:masterfrom
bchrobot:feat/support-discovery-via-cluster-shards-command
Open

bchrobot wants to merge 4 commits into
redis:masterfrom
bchrobot:feat/support-discovery-via-cluster-shards-command

Conversation

@bchrobot

@bchrobot bchrobot commented Aug 14, 2026

Copy link
Copy Markdown

Description of change

Add support for cluster discovery via CLUSTER SHARDS rather than CLUSTER SLOTS, deprecated in Redis 7.0+.

This introduces ClusterTopologyProvider/AsyncClusterTopologyProvider, mirroring the existing PolicyResolver pattern: a provider names the topology command and parses its reply, while NodesManager keeps connection handling and cache construction. Adding a source is now a new subclass rather than a branch in initialize().

CLUSTER SHARDS requires Redis 7.0+ and returns one entry per shard rather than per slot range, so replies stay small on clusters with fragmented slot maps. It is strictly opt-in via the new topology_provider kwarg; the default remains CLUSTER SLOTS.

The shards parser is tolerant of every shape the reply arrives in, because the async stack installs a CLUSTER SHARDS response callback on its node connections while the sync stack receives the raw wire reply.

Replicas reported as failed or loading are excluded; an unhealthy primary is retained, since dropping it would leave its slots uncovered.

Pull Request check-list

Please make sure to review and check all of these items:

  • Do tests and lints pass with this change?
  • Do the CI tests pass with this change (enable it first in your forked repo and wait for the github action build to finish)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?
  • Is there an example added to the examples folder (if applicable)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.


Note

Medium Risk
Changes how cluster slot maps are built on init and refresh; wrong parsing or replica filtering could misroute traffic, though defaults preserve prior behavior and coverage is extensive.

Overview
Introduces pluggable cluster topology discovery via a new topology_provider argument on sync and async RedisCluster. Default behavior is unchanged (CLUSTER SLOTS through ClusterSlotsTopologyProvider); callers can opt into CLUSTER SHARDS (Redis 7.0+) with ClusterShardsTopologyProvider for more compact replies on fragmented slot maps.

NodesManager no longer parses CLUSTER SLOTS inline—it runs the provider’s command and builds slot/node caches from normalized (start_slot, end_slot, primary, replicas) tuples. The shards parser handles RESP2/RESP3 shapes, picks primaries by role, skips unhealthy replicas, supports prefer_tls_port, and leaves empty/null endpoints for the existing “use the queried startup host” fallback (without routing through internal ip behind load balancers).

Topology refresh errors now distinguish unsupported topology commands (“unknown subcommand”) from cluster mode disabled. Docs cover configuration, async providers, and subclassing ClusterTopologyProvider for custom discovery.

Reviewed by Cursor Bugbot for commit c7b7177. Bugbot is set up for automated code reviews on this repo. Configure here.

@bchrobot bchrobot changed the title Feat/support discovery via cluster shards command feat: support cluster topology discovery via CLUSTER SHARDS command Aug 14, 2026
@bchrobot
bchrobot marked this pull request as ready for review August 14, 2026 13:02
Comment thread redis/cluster_topology.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 822402dc6c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread redis/cluster_topology.py
Comment thread redis/cluster.py Outdated
Comment thread redis/cluster_topology.py
endpoint = _as_str(node.get("endpoint", ""))
host = endpoint or _as_str(node.get("ip", ""))

port_keys = ("tls-port", "port") if prefer_tls_port else ("port", "tls-port")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prefer TLS ports automatically for SSL cluster clients

When a caller opts into ClusterShardsTopologyProvider() on a TLS cluster using ssl=True or rediss://, Redis can return both the non-TLS port and the tls-port in CLUSTER SHARDS; this default ordering selects the plain TCP port first, then NodesManager builds SSL connections to that non-TLS port and routed commands fail after discovery. The client already knows it is using SSL, so the shards topology path should select tls-port automatically in that configuration instead of requiring a second, easy-to-miss provider flag.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reasonable point, but deferring it rather than changing it here.

Two reasons. Auto-detecting from the client SSL config would mean the parser reads connection kwargs, which costs the property that makes it cheap to test — it is currently pure and covered directly across all four response shapes. And ssl=True does not strictly imply the TLS port is wanted; a node can advertise both, and the choice is a deployment detail.

The explicit prefer_tls_port flag is discoverable from the provider signature and documented in the Topology Discovery section. If real usage shows the default trips people up on TLS clusters, auto-selection with the flag as an override is a clean follow-up.

Leaving this thread open for a maintainer to weigh in.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit bbaf4b1. Configure here.

Comment thread redis/cluster.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbaf4b1cf3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread redis/cluster_topology.py Outdated
@petyaslavova

Copy link
Copy Markdown
Collaborator

Hey @bchrobot, thank you for your contribution! We will have a look at it soon!

@Mukller Mukller left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified locally against upstream master and this branch (Python 3.13; no live cluster in this environment — noted where it matters).

Test results:

  • pytest tests/test_cluster.py -k "shards or topology or slots"40 passed (8 setup errors = server-dependent fixtures without a local Redis)
  • Same filter, async suite — 24 passed, 4 failed; those exact 4 fail identically on upstream master (test_cluster_slots[pool], test_cluster_addslots[pool], etc. — ConnectionRefused class), so unrelated to this diff.

Design assessment — this is a clean abstraction:

  1. The new redis/cluster_topology.py isolates all reply-shape knowledge in one module: _as_mapping normalizes RESP3 maps vs RESP2 flat arrays, _slot_ranges handles both paired and flat slot lists, and each provider exposes .command + .parse() — so adding future topology commands is a subclass away.
  2. Default wiring keeps back-compat: RedisCluster(topology_provider=AsyncClusterSlotsTopologyProvider()) reproduces today's CLUSTER SLOTS behavior byte-for-byte path-wise.
  3. The LB-endpoint fix (commit title) has a proper rationale comment: a node that doesn't know its own address (behind a load balancer) now yields an empty host instead of the unreachable internal ip, letting the caller reuse the queried host. That's the right call — substituting ip there produces connections that can never succeed.

Docs: clustering.rst/connections.rst additions document the provider injection point accurately per the implementation.

Caveat stated plainly: I could not exercise live CLUSTER SHARDS round-trips here, so parser correctness against real 7.x/8.x SHARDS replies rests on the branch's own added tests (which are thorough — 444 new lines covering RESP2/RESP3 shapes, TLS preference, unknown endpoints).

Approving — solid groundwork for SHARDS support.

@bchrobot
bchrobot force-pushed the feat/support-discovery-via-cluster-shards-command branch from bbaf4b1 to 1111849 Compare August 23, 2026 10:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1111849b02

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread redis/cluster_topology.py Outdated
@bchrobot
bchrobot force-pushed the feat/support-discovery-via-cluster-shards-command branch from 1111849 to 7370104 Compare September 3, 2026 21:42

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 737010414f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread redis/cluster_topology.py Outdated
NodesManager hardcoded CLUSTER SLOTS and read the reply positionally inline,
leaving no seam for an alternative topology source.

Introduce ClusterTopologyProvider / AsyncClusterTopologyProvider, mirroring the
existing PolicyResolver pattern: a provider names the topology command and parses
its reply, while NodesManager keeps connection handling and cache construction.
Adding a source is now a new subclass rather than a branch in initialize().

CLUSTER SHARDS requires Redis 7.0+ and returns one entry per shard rather than
per slot range, so replies stay small on clusters with fragmented slot maps. It
is strictly opt-in via the new topology_provider kwarg; the default remains
CLUSTER SLOTS.

The shards parser is tolerant of every shape the reply arrives in, because the
async stack installs a CLUSTER SHARDS response callback on its node connections
while the sync stack receives the raw wire reply.

Replicas reported as failed or loading are excluded; an unhealthy primary is
retained, since dropping it would leave its slots uncovered.
@bchrobot
bchrobot force-pushed the feat/support-discovery-via-cluster-shards-command branch from 97d72a7 to c7b7177 Compare September 11, 2026 09:21
@bchrobot

Copy link
Copy Markdown
Author

Rebased on upstream master to address conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants