Skip to content

Commit 041bab0

Browse files
committed
fix shoham comments 2
Signed-off-by: BoazBD <boaz@bardavid.com>
1 parent 7ade727 commit 041bab0

File tree

10 files changed

+289
-220
lines changed

10 files changed

+289
-220
lines changed

.github/workflows/python.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ jobs:
241241
run: |
242242
python -m pip install --upgrade pip
243243
pip install sphinx sphinx-rtd-theme
244-
pip install -r dev_requirements.txt
245244
246245
- name: Build docs
247246
working-directory: ./python/docs

python/python/glide/async_commands/batch.py

Lines changed: 87 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
22

33
import threading
4-
from abc import ABC
54
from typing import List, Mapping, Optional, Tuple, TypeVar, Union
65

76
from deprecated import deprecated
@@ -61,26 +60,33 @@
6160
TBatch = TypeVar("TBatch", bound="BaseBatch")
6261

6362

64-
class BaseBatch(ABC):
63+
class BaseBatch:
6564
"""
66-
Base class encompassing shared commands for both standalone and cluster mode implementations in batch.
67-
68-
See [Transactions](https://valkey.io/topics/transactions/) and
69-
[Pipelines](https://valkey.io/topics/pipelines/) for details.
65+
Base class encompassing shared commands for both standalone and cluster server installations.
66+
Batches allow the execution of a group of commands in a single step.
7067
7168
Batch Response:
72-
The response for each command depends on the executed command. Specific response types
73-
are documented alongside each method.
69+
An ``array`` of command responses is returned by the client ``exec`` command, in the order they were given.
70+
Each element in the array represents a command given to the batch.
71+
The response for each command depends on the executed Valkey command.
72+
Specific response types are documented alongside each method.
7473
7574
Args:
7675
is_atomic (bool): Determines whether the batch is atomic or non-atomic.
77-
If `True`, the batch will be executed as an atomic transaction.
78-
If `False`, the batch will be executed as a non-atomic pipeline.
79-
See [Valkey Transactions](https://valkey.io/topics/transactions/) and
80-
[Valkey Pipelines](https://valkey.io/topics/pipelines/) for more details.
76+
If ``True``, the batch will be executed as an atomic transaction.
77+
If ``False``, the batch will be executed as a non-atomic pipeline.
78+
79+
See [Transactions](https://valkey.io/topics/transactions/) and [Pipelines](https://valkey.io/topics/pipelines/) for details.
80+
8181
"""
8282

8383
def __init__(self, is_atomic: bool) -> None:
84+
"""
85+
Args:
86+
is_atomic (bool): Determines whether the batch is atomic or non-atomic.
87+
If `True`, the batch will be executed as an atomic transaction.
88+
If `False`, the batch will be executed as a non-atomic pipeline.
89+
"""
8490
self.commands: List[Tuple[RequestType.ValueType, List[TEncodable]]] = []
8591
self.lock = threading.Lock()
8692
self.is_atomic = is_atomic
@@ -278,7 +284,7 @@ def custom_command(self: TBatch, command_args: List[TEncodable]) -> TBatch:
278284
Example:
279285
Append a command to list of all pub/sub clients:
280286
281-
>>> transaction.customCommand(["CLIENT", "LIST","TYPE", "PUBSUB"])
287+
>>> batch.customCommand(["CLIENT", "LIST","TYPE", "PUBSUB"])
282288
"""
283289
return self.append_command(RequestType.CustomCommand, command_args)
284290

@@ -366,7 +372,7 @@ def config_set(
366372
Command response:
367373
OK: Returns OK if all configurations have been successfully set.
368374
369-
Otherwise, the transaction fails with an error.
375+
Otherwise, the command fails with an error.
370376
"""
371377
parameters: List[TEncodable] = []
372378
for pair in parameters_map.items():
@@ -401,8 +407,10 @@ def mset(self: TBatch, key_value_map: Mapping[TEncodable, TEncodable]) -> TBatch
401407
and the keys in `key_value_map` map to different hash slots,
402408
the command will be split across these slots and executed separately for each.
403409
This means the command is atomic only at the slot level.
404-
405-
See [valkey.io](https://valkey.io/commands/mset/) for more details.
410+
If one or more slot-specific requests fail, the entire call will return the first encountered error, even
411+
though some requests may have succeeded while others did not.
412+
If this behavior impacts your application logic, consider splitting the
413+
request into sub-requests per slot to ensure atomicity.
406414
"""
407415
parameters: List[TEncodable] = []
408416
for pair in key_value_map.items():
@@ -448,6 +456,10 @@ def mget(self: TBatch, keys: List[TEncodable]) -> TBatch:
448456
In cluster mode, if this command is used in a non-atomic batch (pipeline)
449457
and the keys map to different hash slots, the command will be split across these slots
450458
and executed separately for each. This means the command is atomic only at the slot level.
459+
If one or more slot-specific requests fail, the entire call will return the first encountered error, even
460+
though some requests may have succeeded while others did not.
461+
If this behavior impacts your application logic, consider splitting the
462+
request into sub-requests per slot to ensure atomicity.
451463
"""
452464
return self.append_command(RequestType.MGet, keys)
453465

@@ -473,7 +485,7 @@ def config_rewrite(self: TBatch) -> TBatch:
473485
474486
Command response:
475487
OK: OK is returned when the configuration was rewritten properly.
476-
Otherwise, the transaction fails with an error.
488+
Otherwise, the command fails with an error.
477489
"""
478490
return self.append_command(RequestType.ConfigRewrite, [])
479491

@@ -752,7 +764,7 @@ def hlen(self: TBatch, key: TEncodable) -> TBatch:
752764
Command response:
753765
int: The number of fields in the hash, or 0 when the key does not exist.
754766
755-
If `key` holds a value that is not a hash, the batch fails with an error.
767+
If `key` holds a value that is not a hash, the command fails with an error.
756768
"""
757769
return self.append_command(RequestType.HLen, [key])
758770

@@ -5294,30 +5306,40 @@ def sort_store(
52945306

52955307
class Batch(BaseBatch):
52965308
"""
5297-
Extends BaseBatch class for standalone commands that are not supported in cluster mode.
5309+
Batch implementation for standalone GlideClient. Batches allow the execution of a group
5310+
of commands in a single step.
52985311
5299-
Command Response:
5300-
The response for each command depends on the executed command. Specific response types
5301-
are documented alongside each method.
5312+
Batch Response:
5313+
An ``array`` of command responses is returned by the client ``exec`` command,
5314+
in the order they were given. Each element in the array represents a command given to the Batch.
5315+
The response for each command depends on the executed Valkey command.
5316+
Specific response types are documented alongside each method.
5317+
5318+
Args:
5319+
is_atomic (bool): Determines whether the batch is atomic or non-atomic. If ``True``,
5320+
the batch will be executed as an atomic transaction. If ``False``,
5321+
the batch will be executed as a non-atomic pipeline.
5322+
5323+
See [Transactions](https://valkey.io/topics/transactions/) and [Pipelines](https://valkey.io/topics/pipelining/) for details.
53025324
53035325
Note for Standalone Mode (Cluster Mode Disabled):
53045326
Standalone Batches are executed on the primary node.
53055327
5306-
Transaction Example:
5307-
>>> transaction = Batch(is_atomic=True)
5328+
Example (Atomic Batch - Transaction):
5329+
>>> transaction = Batch(is_atomic=True) # Atomic (Transaction)
53085330
>>> transaction.set("key", "value")
5309-
>>> transaction.select(1) # Standalone command
53105331
>>> transaction.get("key")
5311-
>>> await client.exec(transaction)
5312-
[OK , OK , None]
5313-
5314-
Pipeline Example:
5315-
>>> pipeline = Batch(is_atomic=True)
5316-
>>> pipeline.set("key", "value")
5317-
>>> pipeline.select(1) # Standalone command
5318-
>>> pipeline.get("key")
5319-
>>> await client.exec(pipeline)
5320-
[OK , OK , None]
5332+
>>> result = await client.exec(transaction)
5333+
>>> assert result == [OK, b"value"]
5334+
5335+
Example (Non-Atomic Batch - Pipeline):
5336+
>>> pipeline = Batch(is_atomic=False) # Non-Atomic (Pipeline)
5337+
>>> pipeline.set("key1", "value1")
5338+
>>> pipeline.set("key2", "value2")
5339+
>>> pipeline.get("key1")
5340+
>>> pipeline.get("key2")
5341+
>>> result = await client.exec(pipeline)
5342+
>>> assert result == [OK, OK, b"value1", b"value2"]
53215343
"""
53225344

53235345
# TODO: add SLAVEOF and all SENTINEL commands
@@ -5408,14 +5430,38 @@ def publish(self, message: TEncodable, channel: TEncodable) -> "Batch":
54085430

54095431
class ClusterBatch(BaseBatch):
54105432
"""
5411-
Extends BaseBatch class for cluster mode commands that are not supported in standalone.
5433+
Batch implementation for cluster GlideClusterClient. Batches allow the execution of a group
5434+
of commands in a single step.
54125435
5413-
Command Response:
5414-
The response for each command depends on the executed command. Specific response types
5415-
are documented alongside each method.
5436+
Batch Response:
5437+
An ``array`` of command responses is returned by the client ``exec`` command,
5438+
in the order they were given. Each element in the array represents a command given to the ClusterBatch.
5439+
The response for each command depends on the executed Valkey command.
5440+
Specific response types are documented alongside each method.
5441+
5442+
Args:
5443+
is_atomic (bool): Determines whether the batch is atomic or non-atomic. If ``True``,
5444+
the batch will be executed as an atomic transaction. If ``False``,
5445+
the batch will be executed as a non-atomic pipeline.
5446+
5447+
See [Transactions](https://valkey.io/topics/transactions/) and [Pipelines](https://valkey.io/topics/pipelining/) for details.
5448+
5449+
Example (Atomic Batch - Transaction) in a Cluster:
5450+
>>> transaction = ClusterBatch(is_atomic=True) # Atomic (Transaction)
5451+
>>> transaction.set("key", "value")
5452+
>>> transaction.get("key")
5453+
>>> result = await client.exec(transaction)
5454+
>>> assert result == [OK, b"value"]
5455+
5456+
Example (Non-Atomic Batch - Pipeline) in a Cluster:
5457+
>>> pipeline = ClusterBatch(is_atomic=False) # Non-Atomic (Pipeline)
5458+
>>> pipeline.set("key1", "value1")
5459+
>>> pipeline.set("key2", "value2")
5460+
>>> pipeline.get("key1")
5461+
>>> pipeline.get("key2")
5462+
>>> result = await client.exec(pipeline)
5463+
>>> assert result == [OK, OK, b"value1", b"value2"]
54165464
5417-
When the client is configured to read from replicas, read commands
5418-
in a non-atomic batches will be distributed in a round-robin manner across the replicas.
54195465
"""
54205466

54215467
def copy(

python/python/glide/async_commands/cluster_commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ async def exec(
192192
... raise_on_error=False # Do not raise an error on failure
193193
... )
194194
>>> print(f"Atomic Batch Result: {atomic_result}")
195-
# Output: [OK, 2, 2]
195+
# Output: Atomic Batch Result: [OK, 2, 2]
196196
197197
# Example 4: Non-atomic batch with retry options
198198
>>> non_atomic_batch = ClusterBatch(is_atomic=False)
@@ -206,7 +206,7 @@ async def exec(
206206
... retry_connection_error=False
207207
... )
208208
>>> print(f"Non-Atomic Batch Result: {non_atomic_result}")
209-
# Output: [OK, OK, value1, value2]
209+
# Output: Non-Atomic Batch Result: [OK, OK, value1, value2]
210210
"""
211211
commands = batch.commands[:]
212212
return await self._execute_batch(

python/python/glide/async_commands/core.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6980,9 +6980,9 @@ async def fcall_ro(
69806980

69816981
async def watch(self, keys: List[TEncodable]) -> TOK:
69826982
"""
6983-
Marks the given keys to be watched for conditional execution of a batch. Batches
6984-
will only execute commands if the watched keys are not modified before execution of the
6985-
batch.
6983+
Marks the given keys to be watched for conditional execution of an atomic batch (Transaction).
6984+
Transactions will only execute commands if the watched keys are not modified before execution of the
6985+
transaction.
69866986
69876987
See [valkey.io](https://valkey.io/commands/watch) for more details.
69886988
@@ -7004,17 +7004,17 @@ async def watch(self, keys: List[TEncodable]) -> TOK:
70047004
Examples:
70057005
>>> await client.watch("sampleKey")
70067006
'OK'
7007-
>>> batch.set("sampleKey", "foobar")
7008-
>>> await client.exec(batch)
7007+
>>> transaction.set("sampleKey", "foobar")
7008+
>>> await client.exec(transaction)
70097009
'OK' # Executes successfully and keys are unwatched.
70107010
70117011
>>> await client.watch("sampleKey")
70127012
'OK'
7013-
>>> batch.set("sampleKey", "foobar")
7013+
>>> transaction.set("sampleKey", "foobar")
70147014
>>> await client.set("sampleKey", "hello world")
70157015
'OK'
7016-
>>> await client.exec(batch)
7017-
None # None is returned when the watched key is modified before batch execution.
7016+
>>> await client.exec(transaction)
7017+
None # None is returned when the watched key is modified before transaction execution.
70187018
"""
70197019

70207020
return cast(

python/python/glide/async_commands/server_modules/json_batch.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Examples:
55
>>> import json
66
>>> from glide import json_batch
7-
>>> batch = ClusterBatch()
7+
>>> batch = ClusterBatch(is_atomic=True)
88
>>> value = {'a': 1.0, 'b': 2}
99
>>> json_str = json.dumps(value) # Convert Python dictionary to JSON string using json.dumps()
1010
>>> json_batch.set(batch, "doc", "$", json_str)
@@ -118,10 +118,15 @@ def mget(
118118
Retrieves the JSON values at the specified `path` stored at multiple `keys`.
119119
120120
Note:
121-
If the batch is a transaction (is_atomic=True), then all keys must map to the same slot.
122-
In cluster mode, if this command is used in a non-atomic batch (pipeline)
123-
and the keys map to different hash slots, the command will be split across these slots
124-
and executed separately for each. This means the command is atomic only at the slot level.
121+
When in cluster mode:
122+
- If the batch is an atomic batch (transaction), then all keys must map to the same slot.
123+
- If the batch is a non-atomic batch (pipeline), and the keys map to different hash slots,
124+
the command will be split across these slots and executed separately for each.
125+
This means the command is atomic only at the slot level. If one or more slot-specific
126+
requests fail, the entire call will return the first encountered error, even
127+
though some requests may have succeeded while others did not.
128+
If this behavior impacts your application logic, consider splitting the
129+
request into sub-requests per slot to ensure atomicity.
125130
126131
Args:
127132
batch (TBatch): The batch to execute the command.

0 commit comments

Comments
 (0)