Skip to content

Commit aa3d32a

Browse files
committed
feat(DEVC-1286): upgrade redis-py to 6.4.0; bump redis version to redis==7.4.0; few updates at UserRedisSdk
1 parent bf8f2db commit aa3d32a

4 files changed

Lines changed: 65 additions & 17 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ up-cache:
112112
-d \
113113
--name python-sdk-redis \
114114
-p 6379:6379 \
115-
redis:7.4.3
115+
redis:7.4.0
116116

117117
# down-cache: Stop Redis.
118118
.PHONY: down-cache

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ dependencies = [
1717
"fakeredis >=2.30.0, <2.32.0",
1818
"pydantic >= 2.0, <3.0",
1919
"pydantic-settings >=2.0, <3.0",
20-
"redis == 6.2.0",
20+
"redis == 6.4.0",
2121
"requests >=2.32.3, <3.0.0",
2222
"urllib3 == 2.5.0",
2323
"semver==3.0.4"

src/corva/service/cache_sdk.py

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
import datetime
2-
from typing import (
3-
Dict,
4-
Optional,
5-
Protocol,
6-
Sequence,
7-
Tuple,
8-
Union,
9-
cast,
10-
)
2+
from functools import wraps
3+
from typing import Dict, Optional, Protocol, Sequence, Tuple, Union, cast
114

125
import fakeredis
136
import redis
147

158
from corva import cache_adapter
16-
from corva.cache_adapter import HashMigrator
179

1810

1911
class UserCacheSdkProtocol(Protocol):
@@ -62,18 +54,57 @@ def __init__(
6254
elif redis_client is None:
6355
redis_client = redis.Redis.from_url(url=redis_dsn, decode_responses=True)
6456

65-
migrator = HashMigrator(hash_name, redis_client)
66-
migrator.run()
67-
hash_name = HashMigrator.NEW_HASH_PREFIX + hash_name
57+
# Lazy migration: do not run on init; defer until first read/write/delete
58+
self._original_hash_name = hash_name
59+
self._redis_client = cast(redis.Redis, redis_client)
60+
self._migrated = False
6861

6962
self.cache_repo = cache_adapter.RedisRepository(
70-
hash_name=hash_name,
71-
client=cast(redis.Redis, redis_client),
63+
hash_name=cache_adapter.HashMigrator.NEW_HASH_PREFIX + hash_name,
64+
client=self._redis_client,
7265
)
7366

67+
@staticmethod
68+
def ensure_migrated_once(method):
69+
"""
70+
A static method decorator that ensures a specific migration process
71+
has been executed before invoking the decorated method. Once the
72+
migration is attempted, the decorator marks it as complete,
73+
regardless of the outcome, to optimize subsequent calls.
74+
75+
Args:
76+
method (Callable): The `UserRedisSdk.method` to be decorated.
77+
78+
Returns:
79+
Callable: The wrapped method which ensures that the migration process
80+
has been attempted before execution.
81+
"""
82+
83+
@wraps(method)
84+
def wrapper(self, *args, **kwargs):
85+
86+
if not self._migrated:
87+
migrator = cache_adapter.HashMigrator(
88+
hash_name=self._original_hash_name,
89+
client=self._redis_client,
90+
)
91+
try:
92+
migrator.run()
93+
finally:
94+
# Regardless of outcome (True/False), mark as attempted to avoid
95+
# repeating the check on every call. Subsequent calls operate on
96+
# the new-hash namespace.
97+
self._migrated = True
98+
99+
return method(self, *args, **kwargs)
100+
101+
return wrapper
102+
103+
@ensure_migrated_once
74104
def set(self, key: str, value: str, ttl: int = SIXTY_DAYS) -> None:
75105
self.cache_repo.set(key=key, value=value, ttl=ttl)
76106

107+
@ensure_migrated_once
77108
def set_many(
78109
self, data: Sequence[Union[Tuple[str, str], Tuple[str, str, int]]]
79110
) -> None:
@@ -85,20 +116,26 @@ def set_many(
85116
]
86117
self.cache_repo.set_many(data=prepared_data)
87118

119+
@ensure_migrated_once
88120
def get(self, key: str) -> Optional[str]:
89121
return self.cache_repo.get(key=key)
90122

123+
@ensure_migrated_once
91124
def get_many(self, keys: Sequence[str]) -> Dict[str, Optional[str]]:
92125
return self.cache_repo.get_many(keys=keys)
93126

127+
@ensure_migrated_once
94128
def get_all(self) -> Dict[str, str]:
95129
return self.cache_repo.get_all()
96130

131+
@ensure_migrated_once
97132
def delete(self, *, key: str) -> None:
98133
self.cache_repo.delete(key=key)
99134

135+
@ensure_migrated_once
100136
def delete_many(self, keys: Sequence[str]) -> None:
101137
self.cache_repo.delete_many(keys=keys)
102138

139+
@ensure_migrated_once
103140
def delete_all(self) -> None:
104141
self.cache_repo.delete_all()

tests/unit/test_manual_cache_init.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,14 @@ def test_manual_cache_init():
77
"""
88
cache = UserRedisSdk("test", "redis://localhost:6379", redis_client=None)
99
assert cache.cache_repo.client is not None
10+
11+
12+
def test__migration_not_called_on_user_redis_sdk_init__success():
13+
14+
cache = UserRedisSdk("test", "redis://localhost:6379", use_fakes=True)
15+
16+
assert cache._migrated is False
17+
18+
cache.get("key")
19+
20+
assert cache._migrated is True

0 commit comments

Comments
 (0)