Skip to content

Commit 191524e

Browse files
Added a locl digest command to the client to execute the XXH3 locally rather than asking the server for it
1 parent 201c3c9 commit 191524e

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ classifiers = [
2828
"Programming Language :: Python :: Implementation :: CPython",
2929
"Programming Language :: Python :: Implementation :: PyPy",
3030
]
31-
dependencies = ['async-timeout>=4.0.3; python_full_version<"3.11.3"']
31+
dependencies = [
32+
'async-timeout>=4.0.3; python_full_version<"3.11.3"',
33+
'xxhash~=3.6.0',
34+
]
3235

3336
[project.optional-dependencies]
3437
hiredis = [

redis/commands/core.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import datetime
44
import hashlib
5+
import xxhash
56
import warnings
67
from enum import Enum
78
from typing import (
@@ -23,6 +24,7 @@
2324
Union,
2425
)
2526

27+
from docs.conf import version
2628
from redis.exceptions import ConnectionError, DataError, NoScriptError, RedisError
2729
from redis.typing import (
2830
AbsExpiryT,
@@ -1888,6 +1890,27 @@ def expiretime(self, key: str) -> int:
18881890
"""
18891891
return self.execute_command("EXPIRETIME", key)
18901892

1893+
@experimental_method()
1894+
def digest_local(self, value: Union[bytes, str]) -> str:
1895+
"""
1896+
Compute the hexadecimal digest of the value locally, without sending it to the server.
1897+
1898+
This is useful for conditional operations like IFDEQ/IFDNE where you need to
1899+
compute the digest client-side before sending a command.
1900+
1901+
Warning:
1902+
**Experimental** - This API may change or be removed without notice.
1903+
1904+
Arguments:
1905+
- value: Union[bytes, str] - the value to compute the digest of.
1906+
1907+
Returns:
1908+
- (str) the XXH3 digest of the value as a hex string (16 hex characters)
1909+
1910+
For more information, see https://redis.io/commands/digest
1911+
"""
1912+
return xxhash.xxh3_64(value).hexdigest()
1913+
18911914
@experimental_method()
18921915
def digest(self, name: KeyT) -> Optional[str]:
18931916
"""

tests/test_commands.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,6 +2575,9 @@ def test_set_ifdeq_and_ifdne(self, r, val):
25752575
d = self._server_xxh3_digest(r, "k")
25762576
assert d is not None
25772577

2578+
# sanity check: local digest matches server's
2579+
assert d == r.digest_local(val)
2580+
25782581
# IFDEQ must match to set; if key missing => won't create
25792582
assert r.set("k", b"X", ifdeq=d) is True
25802583
assert r.get("k") == b"X"

0 commit comments

Comments
 (0)