Skip to content

fix: keep pooled connections that hold cache invalidation messages in BlockingConnectionPool - #377

Open
simpleqt wants to merge 1 commit into
valkey-io:mainfrom
simpleqt:fix/blocking-pool-cache-invalidations
Open

simpleqt wants to merge 1 commit into
valkey-io:mainfrom
simpleqt:fix/blocking-pool-cache-invalidations

Conversation

@simpleqt

Copy link
Copy Markdown
Contributor

Pull Request check-list

  • 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)?

Description of change

BlockingConnectionPool.get_connection() reconnects a pooled connection whenever connection.can_read() is true. With client-side caching enabled that is wrong: readable data on an idle pooled connection is the push (invalidation) message that the server sent for tracked keys, and _get_from_local_cache() consumes it. Reconnecting discards those messages and flushes the local cache (AbstractConnection.disconnect()), so caching never takes effect with a BlockingConnectionPool, and every invalidation triggers a full disconnect/reconnect (handshake, HELLO, CLIENT TRACKING ON, SELECT).

ConnectionPool.get_connection() already guards this case with connection.client_cache is None, and so does the async pool (valkey/asyncio/connection.py); this change applies the same condition (and comment) to the sync blocking pool.

Verification (no server required, tests/test_connection_pool.py::test_pool_keeps_connection_with_pending_cache_invalidations): a stub connection that reports a pending invalidation message must survive get_connection() in both pool classes. Before the change it is dropped (1 disconnect) in BlockingConnectionPool only; after the change both pools keep it.

Prepared with AI assistance; every line was verified by running the cases above.

BlockingConnectionPool.get_connection() treated any readable data on a
pooled connection as the leftovers of a connection that was returned
before all of its data had been read, and reconnected it. With
client-side caching enabled that data is expected: it holds the
invalidation messages the server pushed while the connection was idle.
Reconnecting throws those messages away and flushes the local cache, so
caching never takes effect with a BlockingConnectionPool.

ConnectionPool.get_connection() already ignores readable data when the
connection has a local cache; do the same in the blocking pool.

Signed-off-by: simpleqt <2015900818@qq.com>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 12:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@mkmkme

mkmkme commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

Thanks for your submissions. We'll review them when we have time.

I noticed you've created a plenty of PRs at this point, so I want to ask: are you fixing issues you stumbled upon during your usage of valkey-py or did you just pointed LLM tool to the repo and instructed it to find bugs?

This branch has not been deployed

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

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants