Skip to content

Commit 537a7b3

Browse files
committed
restructure the hierarchy of clients for better logical isolation
1 parent cc02cd6 commit 537a7b3

File tree

6 files changed

+130
-95
lines changed

6 files changed

+130
-95
lines changed

django_valkey/async_cache/client/default.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from valkey.asyncio.lock import Lock
2323

2424

25-
class AsyncClientMethod(BaseClient):
25+
class AsyncClientMethods(BaseClient):
2626
async def aset(
2727
self,
2828
key,
@@ -1252,7 +1252,7 @@ async def ahrandfield(
12521252
hrandfield = ahrandfield
12531253

12541254

1255-
class AsyncDefaultClient(AsyncClientMethod):
1255+
class BaseAsyncDefaultClient:
12561256
CONNECTION_FACTORY_PATH = "django_valkey.async_cache.pool.AsyncConnectionFactory"
12571257

12581258
def __contains__(self, item):
@@ -1298,3 +1298,7 @@ async def adisconnect(self, index: int = 0, client=None):
12981298
await self.connection_factory.disconnect(client)
12991299

13001300
disconnect = adisconnect
1301+
1302+
1303+
class AsyncDefaultClient(BaseAsyncDefaultClient, AsyncClientMethods):
1304+
pass

django_valkey/async_cache/client/herd.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,18 @@
99
from valkey.exceptions import ConnectionError, ResponseError, TimeoutError
1010
from valkey.typing import EncodableT
1111

12-
from django_valkey.async_cache.client import AsyncDefaultClient
12+
from django_valkey.async_cache.client.default import (
13+
BaseAsyncDefaultClient,
14+
AsyncClientMethods,
15+
)
1316
from django_valkey.client.herd import Marker, _is_expired
1417
from django_valkey.exceptions import ConnectionInterrupted
1518
from django_valkey.typings import KeyT
1619

1720
_main_exceptions = (ConnectionError, ResponseError, TimeoutError, socket.timeout)
1821

1922

20-
class AsyncHerdClient(AsyncDefaultClient):
21-
def __init__(self, *args, **kwargs):
22-
self._marker = Marker()
23-
self._herd_timeout: int = getattr(settings, "CACHE_HERD_TIMEOUT", 60)
24-
super().__init__(*args, **kwargs)
25-
26-
async def _pack(self, value: Any, timeout) -> tuple[Marker, Any, int]:
27-
herd_timeout = (timeout or self._backend.default_timeout) + int(time.time())
28-
return self._marker, value, herd_timeout
29-
30-
async def _unpack(self, value: tuple[Marker, Any, int]) -> tuple[Any, bool]:
31-
try:
32-
marker, unpacked, herd_timeout = value
33-
except (ValueError, TypeError):
34-
return value, False
35-
36-
if not isinstance(marker, Marker):
37-
return value, False
38-
39-
now = time.time()
40-
if herd_timeout < now:
41-
x = now - herd_timeout
42-
return unpacked, _is_expired(x, self._herd_timeout)
43-
44-
return unpacked, False
45-
23+
class AsyncHerdMethods(AsyncClientMethods):
4624
async def aset(
4725
self,
4826
key: KeyT,
@@ -199,3 +177,34 @@ async def atouch(self, key, timeout=DEFAULT_TIMEOUT, version=None, client=None):
199177
return True
200178

201179
touch = atouch
180+
181+
182+
class BaseAsyncHerdClient(BaseAsyncDefaultClient):
183+
def __init__(self, *args, **kwargs):
184+
self._marker = Marker()
185+
self._herd_timeout: int = getattr(settings, "CACHE_HERD_TIMEOUT", 60)
186+
super().__init__(*args, **kwargs)
187+
188+
async def _pack(self, value: Any, timeout) -> tuple[Marker, Any, int]:
189+
herd_timeout = (timeout or self._backend.default_timeout) + int(time.time())
190+
return self._marker, value, herd_timeout
191+
192+
async def _unpack(self, value: tuple[Marker, Any, int]) -> tuple[Any, bool]:
193+
try:
194+
marker, unpacked, herd_timeout = value
195+
except (ValueError, TypeError):
196+
return value, False
197+
198+
if not isinstance(marker, Marker):
199+
return value, False
200+
201+
now = time.time()
202+
if herd_timeout < now:
203+
x = now - herd_timeout
204+
return unpacked, _is_expired(x, self._herd_timeout)
205+
206+
return unpacked, False
207+
208+
209+
class AsyncHerdClient(BaseAsyncHerdClient, AsyncHerdMethods):
210+
pass

django_valkey/client/default.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010

1111
from django_valkey.base_client import BaseClient, _main_exceptions
1212
from django_valkey.exceptions import ConnectionInterrupted
13-
from django_valkey.typing import KeyT
13+
from django_valkey.typings import KeyT
1414
from django_valkey.util import CacheKey
1515

1616
if TYPE_CHECKING:
1717
from valkey.lock import Lock
1818

1919

20-
class SyncClientMethod(BaseClient):
20+
class SyncClientMethods(BaseClient):
2121
def set(
2222
self,
2323
key: KeyT,
@@ -1202,7 +1202,7 @@ def hrandfield(
12021202
return self.reverse_key(result.decode())
12031203

12041204

1205-
class DefaultClient(SyncClientMethod):
1205+
class BaseDefaultClient:
12061206
CONNECTION_FACTORY_PATH = "django_valkey.pool.ConnectionFactory"
12071207

12081208
def _get_client(self, write=True, tried=None, client=None) -> Valkey:
@@ -1245,3 +1245,7 @@ def get_client_with_index(
12451245
self._clients[index] = self.connect(index)
12461246

12471247
return self._clients[index], index
1248+
1249+
1250+
class DefaultClient(BaseDefaultClient, SyncClientMethods):
1251+
pass

django_valkey/client/herd.py

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
from valkey.exceptions import ConnectionError, ResponseError, TimeoutError
1212
from valkey.typing import EncodableT
1313

14-
from django_valkey.client.default import DefaultClient
14+
from django_valkey.client.default import BaseDefaultClient, SyncClientMethods
1515
from django_valkey.exceptions import ConnectionInterrupted
16-
from django_valkey.typing import KeyT
16+
from django_valkey.typings import KeyT
1717

1818
_main_exceptions = (ConnectionError, ResponseError, TimeoutError, socket.timeout)
1919

@@ -33,32 +33,7 @@ def _is_expired(x, herd_timeout: int) -> bool:
3333
return val >= herd_timeout
3434

3535

36-
class HerdClient(DefaultClient):
37-
def __init__(self, *args, **kwargs):
38-
self._marker = Marker()
39-
self._herd_timeout: int = getattr(settings, "CACHE_HERD_TIMEOUT", 60)
40-
super().__init__(*args, **kwargs)
41-
42-
def _pack(self, value: Any, timeout) -> tuple[Marker, Any, int]:
43-
herd_timeout = (timeout or self._backend.default_timeout) + int(time.time())
44-
return self._marker, value, herd_timeout
45-
46-
def _unpack(self, value: tuple[Marker, Any, int]) -> tuple[Any, bool]:
47-
try:
48-
marker, unpacked, herd_timeout = value
49-
except (ValueError, TypeError):
50-
return value, False
51-
52-
if not isinstance(marker, Marker):
53-
return value, False
54-
55-
now = time.time()
56-
if herd_timeout < now:
57-
x = now - herd_timeout
58-
return unpacked, _is_expired(x, self._herd_timeout)
59-
60-
return unpacked, False
61-
36+
class SyncHerdMethods(SyncClientMethods):
6237
def set(
6338
self,
6439
key: KeyT,
@@ -207,3 +182,34 @@ def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None, client=None):
207182

208183
self.set(key, value, timeout=timeout, version=version, client=client)
209184
return True
185+
186+
187+
class BaseHerdClient(BaseDefaultClient):
188+
def __init__(self, *args, **kwargs):
189+
self._marker = Marker()
190+
self._herd_timeout: int = getattr(settings, "CACHE_HERD_TIMEOUT", 60)
191+
super().__init__(*args, **kwargs)
192+
193+
def _pack(self, value: Any, timeout) -> tuple[Marker, Any, int]:
194+
herd_timeout = (timeout or self._backend.default_timeout) + int(time.time())
195+
return self._marker, value, herd_timeout
196+
197+
def _unpack(self, value: tuple[Marker, Any, int]) -> tuple[Any, bool]:
198+
try:
199+
marker, unpacked, herd_timeout = value
200+
except (ValueError, TypeError):
201+
return value, False
202+
203+
if not isinstance(marker, Marker):
204+
return value, False
205+
206+
now = time.time()
207+
if herd_timeout < now:
208+
x = now - herd_timeout
209+
return unpacked, _is_expired(x, self._herd_timeout)
210+
211+
return unpacked, False
212+
213+
214+
class HerdClient(BaseHerdClient, SyncHerdMethods):
215+
pass

django_valkey/client/sharded.py

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,13 @@
1010
from valkey.exceptions import ConnectionError
1111
from valkey.typing import EncodableT
1212

13-
from django_valkey.client.default import DefaultClient
13+
from django_valkey.client.default import BaseDefaultClient, SyncClientMethods
1414
from django_valkey.exceptions import ConnectionInterrupted
1515
from django_valkey.hash_ring import HashRing
1616
from django_valkey.typings import KeyT
1717

1818

19-
class ShardClient(DefaultClient):
20-
_findhash = re.compile(r".*\{(.*)\}.*", re.I)
21-
22-
def __init__(self, *args, **kwargs):
23-
super().__init__(*args, **kwargs)
24-
25-
if not isinstance(self._server, (list, tuple, set)):
26-
self._server = [self._server]
27-
28-
self._ring = HashRing(self._server)
29-
self._server_dict = self.connect()
30-
31-
def get_client(self, *args, **kwargs):
32-
raise NotImplementedError
33-
34-
def connect(self, index: int = 0) -> dict:
35-
connection_dict = {}
36-
for name in self._server:
37-
connection_dict[name] = self.connection_factory.connect(name)
38-
return connection_dict
39-
40-
def get_server_name(self, _key: KeyT) -> str:
41-
key = str(_key)
42-
g = self._findhash.match(key)
43-
if g is not None and len(g.groups()) > 0:
44-
key = g.groups()[0]
45-
return self._ring.get_node(key)
46-
47-
def get_server(self, key: KeyT):
48-
name = self.get_server_name(key)
49-
return self._server_dict[name]
50-
19+
class SyncShardMethods(SyncClientMethods):
5120
def add(
5221
self,
5322
key: KeyT,
@@ -602,3 +571,40 @@ def smismember(
602571
key = self.make_key(key, version=version)
603572
client = self.get_server(key)
604573
return super().smismember(key, *members, version=version, client=client)
574+
575+
576+
class BaseShardClient(BaseDefaultClient):
577+
_findhash = re.compile(r".*\{(.*)\}.*", re.I)
578+
579+
def __init__(self, *args, **kwargs):
580+
super().__init__(*args, **kwargs)
581+
582+
if not isinstance(self._server, (list, tuple, set)):
583+
self._server = [self._server]
584+
585+
self._ring = HashRing(self._server)
586+
self._server_dict = self.connect()
587+
588+
def get_client(self, *args, **kwargs):
589+
raise NotImplementedError
590+
591+
def connect(self, index: int = 0) -> dict:
592+
connection_dict = {}
593+
for name in self._server:
594+
connection_dict[name] = self.connection_factory.connect(name)
595+
return connection_dict
596+
597+
def get_server_name(self, _key: KeyT) -> str:
598+
key = str(_key)
599+
g = self._findhash.match(key)
600+
if g is not None and len(g.groups()) > 0:
601+
key = g.groups()[0]
602+
return self._ring.get_node(key)
603+
604+
def get_server(self, key: KeyT):
605+
name = self.get_server_name(key)
606+
return self._server_dict[name]
607+
608+
609+
class ShardClient(BaseShardClient, SyncShardMethods):
610+
pass

django_valkey/cluster_cache/client/default.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from valkey.typing import KeyT, EncodableT
33

44
from django_valkey.base_client import _main_exceptions
5-
from django_valkey.client.default import SyncClientMethod
5+
from django_valkey.client.default import SyncClientMethods
66
from django_valkey.exceptions import ConnectionInterrupted
77

88

9-
class DefaultClusterClient(SyncClientMethod):
9+
class BaseDefaultClusterClient:
1010
CONNECTION_FACTORY_PATH = (
1111
"django_valkey.cluster_cache.pool.ClusterConnectionFactory"
1212
)
@@ -54,6 +54,8 @@ def readwrite(self, target_nodes=None, client=None):
5454
client = self._get_client(write=True, client=client)
5555
return client.readwrite(target_nodes)
5656

57+
58+
class SyncClusterMethods(SyncClientMethods):
5759
def keys(
5860
self,
5961
pattern="*",
@@ -139,3 +141,7 @@ def flush_cache(self, client=None):
139141
def invalidate_key_from_cache(self, client=None):
140142
client = self._get_client(client=client)
141143
return client.invalidate_key_from_cache()
144+
145+
146+
class DefaultClusterClient(BaseDefaultClusterClient, SyncClusterMethods):
147+
pass

0 commit comments

Comments
 (0)