Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion redis/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -2838,7 +2838,8 @@ def disconnect(self):
if self.connection:
self.connection.disconnect()
for pubsub in self.node_pubsub_mapping.values():
pubsub.connection.disconnect()
if pubsub.connection:
pubsub.connection.disconnect()


class ClusterPipeline(RedisCluster):
Expand Down
42 changes: 42 additions & 0 deletions tests/test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -3289,6 +3289,48 @@ def test_get_redis_connection(self, r):
p = r.pubsub(node=node)
assert p.get_redis_connection() == node.redis_connection

def test_disconnect_with_none_connections(self, r):
"""
Test that disconnect() does not raise when pubsub.connection is None,
both on the ClusterPubSub itself and on node pubsub instances in
node_pubsub_mapping.
"""
node = r.get_default_node()
p = r.pubsub(node=node)
# Ensure self.connection is None
p.connection = None

# Add a mock pubsub with connection=None into node_pubsub_mapping
mock_pubsub = Mock()
mock_pubsub.connection = None
p.node_pubsub_mapping["fake_node"] = mock_pubsub

# Should not raise AttributeError
p.disconnect()

def test_disconnect_calls_disconnect_on_existing_connections(self, r):
"""
Test that disconnect() properly disconnects non-None connections
on both self and node_pubsub_mapping entries.
"""
node = r.get_default_node()
p = r.pubsub(node=node)

# Mock self.connection
mock_conn = Mock()
p.connection = mock_conn

# Add a mock pubsub with a real connection into node_pubsub_mapping
mock_node_conn = Mock()
mock_node_pubsub = Mock()
mock_node_pubsub.connection = mock_node_conn
p.node_pubsub_mapping["fake_node"] = mock_node_pubsub

p.disconnect()

mock_conn.disconnect.assert_called_once()
mock_node_conn.disconnect.assert_called_once()


@pytest.mark.onlycluster
class TestClusterPipeline:
Expand Down
Loading