Skip to content

Conversation

ShubhamKaudewar
Copy link
Contributor

@ShubhamKaudewar ShubhamKaudewar commented Sep 8, 2025

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.

Description of change

Problem:

Client-side caching in redis-py was not consistently invalidating cache entries when Redis keys were passed as bytes while stored as str (or vice versa) as mentioned issue #3618. This caused stale cache values to persist in cases where keys were mixed between str and bytes.

Cause:

The delete_by_redis_keys method previously assumed all Redis keys were str and attempted deletion by encoding bytes to strings. After recent changes that normalized input to bytes, cache entries stored as str were no longer being matched, leading to failed deletions.

Change / Fix:

  • Updated delete_by_redis_keys to temporarily support both str and bytes keys:
  • If a key is passed as str, it checks the cache for both the str and UTF-8 encoded bytes version.
    • If a key is passed as bytes, it checks both the bytes and UTF-8 decoded str version (if possible).
    • This ensures that cache entries are correctly invalidated regardless of key type.
  • Added new unit tests to cover mixed str / bytes scenarios, including overlapping keys and MGET commands.

Benefit:

  • Prevents stale cache entries when using mixed key types.
  • Maintains backward compatibility with existing caches storing str keys.
  • Provides a temporary fix until full internal normalization to bytes is implemented.

Testing:

  • Unit tests confirm:
    • Deletion works when passing bytes for str keys.
    • Deletion works when passing str for bytes keys.
    • Overlapping keys and MGET commands are handled correctly.

@petyaslavova petyaslavova requested a review from Copilot September 9, 2025 13:09
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a client-side cache invalidation bug in redis-py where cache entries were not being properly deleted when Redis keys were provided in different formats (str vs bytes) than how they were originally stored.

  • Modified delete_by_redis_keys method to handle both str and bytes key formats by checking for both versions during cache lookup
  • Updated the method signature to accept Union[List[bytes], List[str]] instead of just List[bytes]
  • Added comprehensive test coverage for mixed key type scenarios including non-UTF-8 bytes handling

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
redis/cache.py Enhanced delete_by_redis_keys to support mixed str/bytes key deletion with UTF-8 encoding/decoding
tests/test_cache.py Added test case for non-UTF-8 bytes key handling in cache invalidation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 217 to 220
for cache_key in self._cache:
if redis_key in cache_key.redis_keys:
if any(candidate in cache_key.redis_keys for candidate in candidates):
keys_to_delete.append(cache_key)
response.append(True)
Copy link
Preview

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

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

This logic appends True to response for each cache key that matches, but it should append one boolean per input redis_key. If multiple cache keys match the same redis_key, this will append multiple True values, making the response list longer than the input list.

Copilot uses AI. Check for mistakes.

@petyaslavova
Copy link
Collaborator

Hi @ShubhamKaudewar, thank you for your contribution! I'll review your change soon. Meanwhile, can you please check the Copilot's comments and linters failures?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants