Skip to content

Commit c9cbf5e

Browse files
committed
adjust the cluster client with the new API
1 parent 620843b commit c9cbf5e

File tree

6 files changed

+78
-24
lines changed

6 files changed

+78
-24
lines changed

django_valkey/base_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from valkey import Valkey
1818
from valkey.asyncio import Valkey as AValkey
19+
from valkey.cluster import ValkeyCluster
1920
from valkey.exceptions import ConnectionError, ResponseError, TimeoutError
2021
from valkey.typing import EncodableT
2122

@@ -61,7 +62,9 @@ def __init__(
6162
or "django_valkey.util.default_reverse_key"
6263
)
6364

64-
self._clients: list[Valkey | AValkey | None] = [None] * len(self._server)
65+
self._clients: list[Valkey | AValkey | ValkeyCluster | None] = [None] * len(
66+
self._server
67+
)
6568
self._options: dict = params.get("OPTIONS", {})
6669
self._replica_read_only = self._options.get("REPLICA_READ_ONLY", True)
6770

django_valkey/cluster_cache/cache.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from valkey.cluster import ValkeyCluster
22

3-
from django_valkey.base import BaseValkeyCache
4-
from django_valkey.cache import CONNECTION_INTERRUPTED
3+
from django_valkey.base import (
4+
BaseValkeyCache,
5+
SyncCacheCommands,
6+
CONNECTION_INTERRUPTED,
7+
)
58
from django_valkey.cluster_cache.client import DefaultClusterClient
69

710

8-
class ClusterValkeyCache(BaseValkeyCache[DefaultClusterClient, ValkeyCluster]):
9-
DEFAULT_CLIENT_CLASS = "django_valkey.cluster_cache.client.DefaultClusterClient"
10-
11+
class ClusterSyncCacheCommands(SyncCacheCommands):
1112
def set(self, *args, **kwargs):
1213
return self.client.set(*args, **kwargs)
1314

@@ -73,3 +74,9 @@ def has_key(self, *args, **kwargs):
7374

7475
def touch(self, *args, **kwargs):
7576
return self.client.touch(*args, **kwargs)
77+
78+
79+
class ClusterValkeyCache(
80+
BaseValkeyCache[DefaultClusterClient, ValkeyCluster], ClusterSyncCacheCommands
81+
):
82+
DEFAULT_CLIENT_CLASS = "django_valkey.cluster_cache.client.DefaultClusterClient"

django_valkey/cluster_cache/client/default.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,51 @@
11
from valkey.cluster import ValkeyCluster
22
from valkey.typing import KeyT, EncodableT
33

4-
from django_valkey.base_client import BaseClient, _main_exceptions
4+
from django_valkey.base_client import _main_exceptions
5+
from django_valkey.client.default import SyncClientMethod
56
from django_valkey.exceptions import ConnectionInterrupted
67

78

8-
class DefaultClusterClient(BaseClient):
9+
class DefaultClusterClient(SyncClientMethod):
910
CONNECTION_FACTORY_PATH = (
1011
"django_valkey.cluster_cache.pool.ClusterConnectionFactory"
1112
)
1213

14+
def _get_client(self, write=True, tried=None, client=None) -> ValkeyCluster:
15+
if client:
16+
return client
17+
return self.get_client(write=write, tried=tried)
18+
19+
def get_client(self, write=True, tried=None) -> ValkeyCluster:
20+
index = self.get_next_client_index(write=write, tried=tried)
21+
22+
if self._clients[index] is None:
23+
self._clients[index] = self.connect(index)
24+
25+
return self._clients[index]
26+
27+
def get_client_with_index(
28+
self, write=True, tried=None
29+
) -> tuple[ValkeyCluster, int]:
30+
index = self.get_next_client_index(write=write, tried=tried)
31+
if self._clients[index] is None:
32+
self._clients[index] = self.connect(index)
33+
34+
return self._clients[index], index
35+
36+
def connect(self, index: int = 0) -> ValkeyCluster:
37+
return self.connection_factory.connect(self._server[index])
38+
39+
def disconnect(self, index: int = 0, client: ValkeyCluster | None = None) -> None:
40+
"""
41+
delegates the connection factory to disconnect the client
42+
"""
43+
if client is None:
44+
client = self._clients[index]
45+
46+
if client is not None:
47+
self.connection_factory.disconnect(client)
48+
1349
def readonly(self, target_nodes=None, client=None):
1450
client = self._get_client(write=True, client=client)
1551
return client.readonly(target_nodes)

tests/conftest.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,21 @@ def cache() -> Iterable[BaseValkeyCache]:
2424
default_cache.clear()
2525

2626

27-
if isawaitable(default_valkey.clear()):
27+
try:
28+
if isawaitable(default_valkey.clear()):
2829

29-
@pytest_asyncio.fixture(loop_scope="session")
30-
async def valkey():
31-
yield default_valkey
32-
await default_valkey.aclear()
30+
@pytest_asyncio.fixture(loop_scope="session")
31+
async def valkey():
32+
yield default_valkey
33+
await default_valkey.aclear()
3334

34-
else:
35+
else:
3536

36-
@pytest.fixture
37-
def valkey() -> Iterable[BaseValkeyCache]:
38-
yield default_valkey
39-
default_valkey.clear()
37+
@pytest.fixture
38+
def valkey() -> Iterable[BaseValkeyCache]:
39+
yield default_valkey
40+
default_valkey.clear()
41+
42+
except AttributeError:
43+
# cluster client doesn't support this feature yet
44+
pass

tests/settings/sqlite_cluster.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
CACHES = {
44
"default": {
55
"BACKEND": "django_valkey.cluster_cache.cache.ClusterValkeyCache",
6-
"LOCATION": ["valkey://127.0.0.1:7005", "valkey://127.0.0.1:7005"],
6+
"LOCATION": ["valkey://127.0.0.1:16379", "valkey://127.0.0.1:16380"],
77
"OPTIONS": {
88
"CLIENT_CLASS": "django_valkey.cluster_cache.client.DefaultClusterClient"
99
},
@@ -17,14 +17,14 @@
1717
},
1818
"sample": {
1919
"BACKEND": "django_valkey.cluster_cache.cache.ClusterValkeyCache",
20-
"LOCATION": "valkey://127.0.0.1:7005:0,valkey://127.0.0.1:7002:0",
20+
"LOCATION": "valkey://127.0.0.1:16381:0,valkey://127.0.0.1:16379:0",
2121
"OPTIONS": {
2222
"CLIENT_CLASS": "django_valkey.cluster_cache.client.DefaultClusterClient"
2323
},
2424
},
2525
"with_prefix": {
2626
"BACKEND": "django_valkey.cluster_cache.cache.ClusterValkeyCache",
27-
"LOCATION": "valkey://127.0.0.1:7005?db=0",
27+
"LOCATION": "valkey://127.0.0.1:16380?db=0",
2828
"OPTIONS": {
2929
"CLIENT_CLASS": "django_valkey.cluster_cache.client.DefaultClusterClient"
3030
},

tests/tests_cluster/test_backend.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,8 @@ def test_srandmember_default_count(self, cache: ClusterValkeyCache):
10621062

10631063
def test_srandmember(self, cache: ClusterValkeyCache):
10641064
cache.sadd("foo", "bar1", "bar2")
1065-
assert cache.srandmember("foo", 1) in [["bar1"], ["bar2"]]
1065+
assert cache.srandmember("foo", 1) in [{"bar1"}, {"bar2"}]
1066+
assert cache.srandmember("foo", 1, return_set=False) in [["bar1"], ["bar2"]]
10661067

10671068
def test_srem(self, cache: ClusterValkeyCache):
10681069
cache.sadd("foo", "bar1", "bar2")
@@ -1071,15 +1072,17 @@ def test_srem(self, cache: ClusterValkeyCache):
10711072

10721073
def test_sscan(self, cache: ClusterValkeyCache):
10731074
cache.sadd("foo", "bar1", "bar2")
1074-
items = cache.sscan("foo")
1075+
cursor, items = cache.sscan("foo")
10751076
assert items == {"bar1", "bar2"}
1077+
assert cursor == 0
10761078

10771079
def test_sscan_with_match(self, cache: ClusterValkeyCache):
10781080
if cache.client._has_compression_enabled():
10791081
pytest.skip("Compression is enabled, sscan with match is not supported")
10801082
cache.sadd("foo", "bar1", "bar2", "zoo")
1081-
items = cache.sscan("foo", match="zoo")
1083+
cursor, items = cache.sscan("foo", match="zoo")
10821084
assert items == {"zoo"}
1085+
assert cursor == 0
10831086

10841087
def test_sscan_iter(self, cache: ClusterValkeyCache):
10851088
cache.sadd("foo", "bar1", "bar2")

0 commit comments

Comments
 (0)