fix: preserve Redis client ownership boundaries - #705
Open
mikemikimike wants to merge 1 commit into
Open
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 9dc39ae. Configure here.
| if self._owns_redis_client: | ||
| self._detach_client_finalizer() | ||
| if self.__redis_client is not None: | ||
| self.__redis_client.close() |
There was a problem hiding this comment.
Failed connect closes the live client
Medium Severity
A failed connect() closes the currently owned Redis client before the replacement is created, so a ConnectionError or missing REDIS_URL leaves the index pointing at a closed client. Later operations keep using that dead connection instead of recovering.
Reviewed by Cursor Bugbot for commit 9dc39ae. Configure here.
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.


Summary
Fixes #660.
SearchIndex.set_client()could keep ownership of a caller-provided Redis client and close it during disconnect or garbage collection. It also left the previously owned client open when replacing it. The syncconnect()path had the corresponding replacement-lifecycle gap.This change closes a previously owned client before replacement, marks clients supplied through
set_client()as unowned, and keeps clients created byconnect()owned by the index. Async ownership behavior is preserved and covered by a focused regression test.Compatibility
Explicitly injected clients are no longer closed by the index, matching constructor injection semantics. Clients created by
connect()remain index-owned and are closed as before. No Redis protocol or data behavior changes.Validation
.venv\\Scripts\\python.exe -m pytest tests/unit/test_connection_normalization.py -q --confcutdir=tests/unit -p pytest_asyncio— 12 passed..venv\\Scripts\\python.exe -m pytest tests/unit/test_index_gc_finalizer.py -q --confcutdir=tests/unit -p pytest_asyncio— 11 passed.python -m ruff check redisvl/index/index.py tests/unit/test_connection_normalization.py tests/unit/test_index_gc_finalizer.py— passed.python -m ruff format --check redisvl/index/index.py tests/unit/test_connection_normalization.py— passed.git diff --check— passed.The repository Docker-based test fixture was attempted, but pulling
redis:8.4failed with a registry EOF before any service started. The changed paths are covered by service-free unit tests; full Docker-backed integration tests were not run.Note
Medium Risk
Changes connection teardown semantics for apps using deprecated
connect()/set_client(); injected clients will no longer be closed by the index, which fixes a bug but may leave connections open if callers relied on the old behavior.Overview
Fixes incorrect Redis client lifecycle on sync
SearchIndexwhen swapping connections:set_client()no longer treats caller-supplied clients as index-owned, andconnect()now closes and detaches a previously index-owned client before opening a new factory connection.SearchIndex.connect()— If the index currently owns its client, the change detaches the GC finalizer, closes that client, then builds a new connection and sets_owns_redis_client = Truesodisconnect()still closes factory-created clients.SearchIndex.set_client()— Same cleanup when replacing an owned client, then sets_owns_redis_client = Falseso injected clients are never closed bydisconnect()or ownership finalizers (aligned with constructorredis_client=behavior).Unit tests in
test_connection_normalization.pylock in: owned client closed onset_client, external client left open ondisconnect;connect()closes the old owned client and keeps ownership of the new one; asyncset_clientdoes not take ownership.Reviewed by Cursor Bugbot for commit 9dc39ae. Bugbot is set up for automated code reviews on this repo. Configure here.