| 35 | |
| 36 | |
| 37 | class RedisCache(AbstractCache): |
| 38 | |
| 39 | def __init__(self) -> None: |
| 40 | # Connect to redis, return redis client |
| 41 | self._redis_client = self._connet_redis() |
| 42 | |
| 43 | @staticmethod |
| 44 | def _connet_redis() -> Redis: |
| 45 | """ |
| 46 | Connect to redis, return redis client, configure redis connection information as needed |
| 47 | :return: |
| 48 | """ |
| 49 | return Redis( |
| 50 | host=db_config.REDIS_DB_HOST, |
| 51 | port=db_config.REDIS_DB_PORT, |
| 52 | db=db_config.REDIS_DB_NUM, |
| 53 | password=db_config.REDIS_DB_PWD, |
| 54 | ) |
| 55 | |
| 56 | def get(self, key: str) -> Any: |
| 57 | """ |
| 58 | Get the value of a key from the cache and deserialize it |
| 59 | :param key: |
| 60 | :return: |
| 61 | """ |
| 62 | value = self._redis_client.get(key) |
| 63 | if value is None: |
| 64 | return None |
| 65 | return pickle.loads(value) |
| 66 | |
| 67 | def set(self, key: str, value: Any, expire_time: int) -> None: |
| 68 | """ |
| 69 | Set the value of a key in the cache and serialize it |
| 70 | :param key: |
| 71 | :param value: |
| 72 | :param expire_time: |
| 73 | :return: |
| 74 | """ |
| 75 | self._redis_client.set(key, pickle.dumps(value), ex=expire_time) |
| 76 | |
| 77 | def keys(self, pattern: str) -> List[str]: |
| 78 | """ |
| 79 | Get all keys matching the pattern |
| 80 | First try KEYS command, if not supported fallback to SCAN |
| 81 | """ |
| 82 | try: |
| 83 | # Try KEYS command first (faster for standard Redis) |
| 84 | return [key.decode() if isinstance(key, bytes) else key for key in self._redis_client.keys(pattern)] |
| 85 | except ResponseError as e: |
| 86 | # If KEYS is not supported (e.g., Redis Cluster or cloud Redis), use SCAN |
| 87 | if "unknown command" in str(e).lower() or "keys" in str(e).lower(): |
| 88 | keys_list: List[str] = [] |
| 89 | cursor = 0 |
| 90 | while True: |
| 91 | cursor, keys = self._redis_client.scan(cursor=cursor, match=pattern, count=100) |
| 92 | keys_list.extend([key.decode() if isinstance(key, bytes) else key for key in keys]) |
| 93 | if cursor == 0: |
| 94 | break |
no outgoing calls