Repository navigation
test(cluster): seed aclear multipage test with one amset - #800
Draft
vishal-bala wants to merge 1 commit into
Draft
vishal-bala wants to merge 1 commit into
vishal-bala wants to merge 1 commit into
Conversation
The test seeded 600 keys with 600 concurrent aset() calls, each a single-key pipeline. On redis-py 8.x, whose async cluster defaults to 100 connections per node, that raised MaxConnectionsError on slow connects; the 8.1.0 pipeline retry then closed the shared client and tore down other coroutines' connections mid-handshake, failing with "'NoneType' object has no attribute 'writelines'" on Python 3.11. Seed with a single amset() instead. The comment that amset writes nothing on an async cluster was stale: #697 fixed that.
vishal-bala
added a commit
that referenced
this pull request
Oct 30, 2026
Co-Authored-By: Claude <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
On the first run of the nightly cluster job (#796),
test_embeddings_cache_aclear_multipage_clusterfailed on the redis-py 8.x leg withAttributeError: 'NoneType' object has no attribute 'writelines'. It passed on the 6.x and 7.x legs, and it passes locally on 8.1.0. The fault is in redis-py 8.x, not RedisVL, but the test only reaches it because of how it seeds its data.Root cause
The test seeded its 600 cache entries with
asyncio.gatherover 600aset()calls on one asyncRedisCluster. Eachasetis a single-key pipeline, so up to about 200 pipelines are in flight on each of the three primaries.redis-py 8.0 lowered the async cluster's default
max_connectionsper node from2**31to 100. When connecting is slow, as on the CI runner, more than 100 pipelines hold a connection at once andClusterNode.acquire_connectionraisesMaxConnectionsError. That error subclassesConnectionError, so the 8.1.0 pipeline treats it as retryable and callscluster_client.aclose(). That closes the shared client and disconnects connections other coroutines are part-way through using. On Python 3.11,asyncio.wait_foryields between the connection'sis_connectedcheck and its write. A connection in the middle of itsCLIENT SETINFOhandshake therefore writes afterdisconnect()has set_writer = None, which is the CI traceback. On Python 3.12 and later the same race surfaces asConnectionErrororTimeoutErrorinstead.A reproduction with redis-py alone (300 concurrent single-key pipelines,
max_connections=4, 20 rounds, local six-node cluster):AttributeError, plusConnectionErrorandMaxConnectionsErrorMaxConnectionsError,ConnectionError,TimeoutErrorMaxConnectionsErroronlyMaxConnectionsErroronlyredis/redis-py#4448, merged but not yet released, stops the pipeline closing the client and makes
MaxConnectionsErrorfail immediately. Once it ships, the old seeding would fail withMaxConnectionsErrorinstead, so the test needs changing either way.Changes
The test now seeds with one
amset()call, which is a single pipeline using at most one connection per node. The comment sayingamsetwrites nothing on an async cluster client was out of date, because #697 fixed that, so it's replaced. The now-unusedimport asynciois removed.Notes
This PR goes between #795 and #796 in the stack: #794 → #795 → this PR → #796. It doesn't depend on #794 or #795. It's stacked because #796's nightly job needs it to pass.
Tested locally:
test_redis_cluster_support.pypass against a local six-node Redis 8.4 cluster (Python 3.14, redis-py 8.1.0).test_semantic_router_cluster_client, errored only because that venv lackssentence-transformers.amsetseeding writes all 600 keys even withmax_connections=4.Not tested:
Cluster tests don't run on pull-request CI, so #796's nightly job is the first place this runs in CI.
Reviewer Brief
Start here:
tests/integration/test_redis_cluster_support.py, the seeding step intest_embeddings_cache_aclear_multipage_cluster. It's the only behavioural change: 600 entries now go in through oneamset()pipeline, not 600 concurrentaset()calls.Not verified: the edited test hasn't run on Python 3.11, where the nightly redis-py 8.x leg failed, or against redis-py 6.x, 7.x or 8.0.x.
requires_clustertests don't run on pull-request CI, so #796's nightly job is the first CI run.Beyond CI: on a local six-node Redis 8.4 cluster (Python 3.14, redis-py 8.1.0), the edited test and its sync twin pass. Single-
amsetseeding wrote all 600 keys withmax_connections=4on both Python 3.11 and 3.14. A redis-py-only script that runs concurrent single-key pipelines on one client reproduced the CIAttributeError55 times in 20 rounds on Python 3.11 with redis-py 8.1.0. The old test itself never failed locally.Reviewed
8e694b3d· Claude Code (claude-opus-5-5) · lenses: correctness, security, design, tests, docs, Redis behaviour