|
18 | 18 | Union, |
19 | 19 | ) |
20 | 20 |
|
| 21 | +from redis._cache import ( |
| 22 | + DEFAULT_BLACKLIST, |
| 23 | + DEFAULT_EVICTION_POLICY, |
| 24 | + DEFAULT_WHITELIST, |
| 25 | + _LocalCache, |
| 26 | +) |
21 | 27 | from redis._parsers import AsyncCommandsParser, Encoder |
22 | 28 | from redis._parsers.helpers import ( |
23 | 29 | _RedisCallbacks, |
@@ -267,6 +273,13 @@ def __init__( |
267 | 273 | ssl_keyfile: Optional[str] = None, |
268 | 274 | protocol: Optional[int] = 2, |
269 | 275 | address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None, |
| 276 | + cache_enable: bool = False, |
| 277 | + client_cache: Optional[_LocalCache] = None, |
| 278 | + cache_max_size: int = 100, |
| 279 | + cache_ttl: int = 0, |
| 280 | + cache_eviction_policy: str = DEFAULT_EVICTION_POLICY, |
| 281 | + cache_blacklist: List[str] = DEFAULT_BLACKLIST, |
| 282 | + cache_whitelist: List[str] = DEFAULT_WHITELIST, |
270 | 283 | ) -> None: |
271 | 284 | if db: |
272 | 285 | raise RedisClusterException( |
@@ -310,6 +323,14 @@ def __init__( |
310 | 323 | "socket_timeout": socket_timeout, |
311 | 324 | "retry": retry, |
312 | 325 | "protocol": protocol, |
| 326 | + # Client cache related kwargs |
| 327 | + "cache_enable": cache_enable, |
| 328 | + "client_cache": client_cache, |
| 329 | + "cache_max_size": cache_max_size, |
| 330 | + "cache_ttl": cache_ttl, |
| 331 | + "cache_eviction_policy": cache_eviction_policy, |
| 332 | + "cache_blacklist": cache_blacklist, |
| 333 | + "cache_whitelist": cache_whitelist, |
313 | 334 | } |
314 | 335 |
|
315 | 336 | if ssl: |
@@ -682,7 +703,6 @@ async def execute_command(self, *args: EncodableT, **kwargs: Any) -> Any: |
682 | 703 | :raises RedisClusterException: if target_nodes is not provided & the command |
683 | 704 | can't be mapped to a slot |
684 | 705 | """ |
685 | | - kwargs.pop("keys", None) # the keys are used only for client side caching |
686 | 706 | command = args[0] |
687 | 707 | target_nodes = [] |
688 | 708 | target_nodes_specified = False |
@@ -1039,16 +1059,24 @@ async def parse_response( |
1039 | 1059 | async def execute_command(self, *args: Any, **kwargs: Any) -> Any: |
1040 | 1060 | # Acquire connection |
1041 | 1061 | connection = self.acquire_connection() |
| 1062 | + keys = kwargs.pop("keys", None) |
1042 | 1063 |
|
1043 | | - # Execute command |
1044 | | - await connection.send_packed_command(connection.pack_command(*args), False) |
1045 | | - |
1046 | | - # Read response |
1047 | | - try: |
1048 | | - return await self.parse_response(connection, args[0], **kwargs) |
1049 | | - finally: |
1050 | | - # Release connection |
| 1064 | + response_from_cache = await connection._get_from_local_cache(args) |
| 1065 | + if response_from_cache is not None: |
1051 | 1066 | self._free.append(connection) |
| 1067 | + return response_from_cache |
| 1068 | + else: |
| 1069 | + # Execute command |
| 1070 | + await connection.send_packed_command(connection.pack_command(*args), False) |
| 1071 | + |
| 1072 | + # Read response |
| 1073 | + try: |
| 1074 | + response = await self.parse_response(connection, args[0], **kwargs) |
| 1075 | + connection._add_to_local_cache(args, response, keys) |
| 1076 | + return response |
| 1077 | + finally: |
| 1078 | + # Release connection |
| 1079 | + self._free.append(connection) |
1052 | 1080 |
|
1053 | 1081 | async def execute_pipeline(self, commands: List["PipelineCommand"]) -> bool: |
1054 | 1082 | # Acquire connection |
|
0 commit comments