valkey-glide 2.0.0rc3__cp310-cp310-macosx_11_0_arm64.whl → 2.2.3__cp310-cp310-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- glide/__init__.py +160 -106
- glide/async_commands/cluster_commands.py +108 -105
- glide/async_commands/core.py +637 -444
- glide/async_commands/{server_modules/ft.py → ft.py} +8 -7
- glide/async_commands/{server_modules/glide_json.py → glide_json.py} +15 -92
- glide/async_commands/standalone_commands.py +27 -58
- glide/glide.cpython-310-darwin.so +0 -0
- glide/glide.pyi +26 -1
- glide/glide_client.py +269 -125
- glide/logger.py +33 -21
- glide/opentelemetry.py +185 -0
- glide_shared/__init__.py +330 -0
- glide_shared/commands/__init__.py +0 -0
- {glide/async_commands → glide_shared/commands}/batch.py +476 -64
- glide_shared/commands/batch_options.py +261 -0
- glide_shared/commands/core_options.py +407 -0
- {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_aggregate_options.py +3 -3
- {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_create_options.py +4 -2
- {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_profile_options.py +4 -4
- {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_search_options.py +4 -2
- {glide/async_commands → glide_shared/commands}/server_modules/json_batch.py +4 -4
- glide_shared/commands/server_modules/json_options.py +93 -0
- {glide/async_commands → glide_shared/commands}/sorted_set.py +2 -2
- {glide/async_commands → glide_shared/commands}/stream.py +1 -1
- {glide → glide_shared}/config.py +386 -61
- {glide → glide_shared}/constants.py +3 -3
- {glide → glide_shared}/exceptions.py +27 -1
- glide_shared/protobuf/command_request_pb2.py +56 -0
- glide_shared/protobuf/connection_request_pb2.py +56 -0
- {glide → glide_shared}/protobuf/response_pb2.py +6 -6
- {glide → glide_shared}/routes.py +54 -15
- valkey_glide-2.2.3.dist-info/METADATA +211 -0
- valkey_glide-2.2.3.dist-info/RECORD +40 -0
- glide/protobuf/command_request_pb2.py +0 -54
- glide/protobuf/command_request_pb2.pyi +0 -1187
- glide/protobuf/connection_request_pb2.py +0 -54
- glide/protobuf/connection_request_pb2.pyi +0 -320
- glide/protobuf/response_pb2.pyi +0 -100
- valkey_glide-2.0.0rc3.dist-info/METADATA +0 -127
- valkey_glide-2.0.0rc3.dist-info/RECORD +0 -37
- {glide/async_commands → glide_shared/commands}/bitmap.py +0 -0
- {glide/async_commands → glide_shared/commands}/command_args.py +0 -0
- {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_constants.py +0 -0
- {glide → glide_shared}/protobuf_codec.py +0 -0
- {valkey_glide-2.0.0rc3.dist-info → valkey_glide-2.2.3.dist-info}/WHEEL +0 -0
|
@@ -4,27 +4,28 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Dict, List, Mapping, Optional, Union, cast
|
|
6
6
|
|
|
7
|
-
from glide.
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
|
|
7
|
+
from glide.glide import ClusterScanCursor, Script
|
|
8
|
+
from glide_shared.commands.batch import ClusterBatch
|
|
9
|
+
from glide_shared.commands.batch_options import ClusterBatchOptions
|
|
10
|
+
from glide_shared.commands.command_args import ObjectType
|
|
11
|
+
from glide_shared.commands.core_options import (
|
|
11
12
|
FlushMode,
|
|
12
13
|
FunctionRestorePolicy,
|
|
13
14
|
InfoSection,
|
|
14
15
|
)
|
|
15
|
-
from
|
|
16
|
+
from glide_shared.constants import (
|
|
16
17
|
TOK,
|
|
17
18
|
TClusterResponse,
|
|
18
19
|
TEncodable,
|
|
19
20
|
TFunctionListResponse,
|
|
20
21
|
TFunctionStatsSingleNodeResponse,
|
|
21
22
|
TResult,
|
|
22
|
-
TSingleNodeRoute,
|
|
23
23
|
)
|
|
24
|
-
from
|
|
25
|
-
from
|
|
24
|
+
from glide_shared.exceptions import RequestError
|
|
25
|
+
from glide_shared.protobuf.command_request_pb2 import RequestType
|
|
26
|
+
from glide_shared.routes import Route
|
|
26
27
|
|
|
27
|
-
from
|
|
28
|
+
from .core import CoreCommands
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
class ClusterCommands(CoreCommands):
|
|
@@ -36,9 +37,13 @@ class ClusterCommands(CoreCommands):
|
|
|
36
37
|
See the [Valkey GLIDE Wiki](https://github.com/valkey-io/valkey-glide/wiki/General-Concepts#custom-command)
|
|
37
38
|
for details on the restrictions and limitations of the custom command API.
|
|
38
39
|
|
|
40
|
+
This function should only be used for single-response commands. Commands that don't return complete response and awaits
|
|
41
|
+
(such as SUBSCRIBE), or that return potentially more than a single response (such as XREAD), or that change the
|
|
42
|
+
client's behavior (such as entering pub/sub mode on RESP2 connections) shouldn't be called using this function.
|
|
43
|
+
|
|
39
44
|
For example - Return a list of all pub/sub clients from all nodes::
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
await client.customCommand(["CLIENT", "LIST","TYPE", "PUBSUB"], AllNodes())
|
|
42
47
|
|
|
43
48
|
Args:
|
|
44
49
|
command_args (List[TEncodable]): List of the command's arguments, where each argument is either a string or bytes.
|
|
@@ -63,13 +68,15 @@ class ClusterCommands(CoreCommands):
|
|
|
63
68
|
"""
|
|
64
69
|
Get information and statistics about the server.
|
|
65
70
|
|
|
71
|
+
Starting from server version 7, command supports multiple section arguments.
|
|
72
|
+
|
|
66
73
|
See [valkey.io](https://valkey.io/commands/info/) for details.
|
|
67
74
|
|
|
68
75
|
Args:
|
|
69
76
|
sections (Optional[List[InfoSection]]): A list of InfoSection values specifying which sections of
|
|
70
77
|
information to retrieve. When no parameter is provided, the default option is assumed.
|
|
71
|
-
route (Optional[Route]): The command will be routed to all primaries, unless `route` is provided, in
|
|
72
|
-
case the client will route the command to the nodes defined by `route`. Defaults to None.
|
|
78
|
+
route (Optional[Route]): The command will be routed to all primaries, unless `route` is provided, in
|
|
79
|
+
which case the client will route the command to the nodes defined by `route`. Defaults to None.
|
|
73
80
|
|
|
74
81
|
Returns:
|
|
75
82
|
TClusterResponse[bytes]: If a single node route is requested, returns a bytes string containing the information for
|
|
@@ -88,128 +95,109 @@ class ClusterCommands(CoreCommands):
|
|
|
88
95
|
self,
|
|
89
96
|
batch: ClusterBatch,
|
|
90
97
|
raise_on_error: bool,
|
|
91
|
-
|
|
92
|
-
timeout: Optional[int] = None,
|
|
93
|
-
retry_server_error: bool = False,
|
|
94
|
-
retry_connection_error: bool = False,
|
|
98
|
+
options: Optional[ClusterBatchOptions] = None,
|
|
95
99
|
) -> Optional[List[TResult]]:
|
|
96
100
|
"""
|
|
97
101
|
Executes a batch by processing the queued commands.
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
See [Valkey Pipelines (Non-Atomic Batches)](https://valkey.io/docs/topics/pipelining/) for details.
|
|
101
|
-
|
|
102
|
-
#### Routing Behavior:
|
|
103
|
-
|
|
104
|
-
- If a `route` is specified:
|
|
105
|
-
- The entire batch is sent to the specified node.
|
|
103
|
+
**Routing Behavior:**
|
|
106
104
|
|
|
105
|
+
- If a `route` is specified in `ClusterBatchOptions`, the entire batch is sent
|
|
106
|
+
to the specified node.
|
|
107
107
|
- If no `route` is specified:
|
|
108
|
-
- Atomic batches (Transactions)
|
|
109
|
-
If no key is found, the request is sent to a random node.
|
|
110
|
-
- Non-atomic batches (Pipelines)
|
|
111
|
-
key's slot. If no key is present, routing follows the
|
|
112
|
-
Multi-node commands are automatically split and
|
|
108
|
+
- **Atomic batches (Transactions):** Routed to the slot owner of the
|
|
109
|
+
first key in the batch. If no key is found, the request is sent to a random node.
|
|
110
|
+
- **Non-atomic batches (Pipelines):** Each command is routed to the node
|
|
111
|
+
owning the corresponding key's slot. If no key is present, routing follows the
|
|
112
|
+
command's request policy. Multi-node commands are automatically split and
|
|
113
|
+
dispatched to the appropriate nodes.
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
**Behavior notes:**
|
|
115
116
|
|
|
116
|
-
- Atomic Batches (Transactions)
|
|
117
|
-
If keys span different slots, the transaction will fail. If the
|
|
118
|
-
`WATCH` command, `
|
|
117
|
+
- **Atomic Batches (Transactions):** All key-based commands must map to the
|
|
118
|
+
same hash slot. If keys span different slots, the transaction will fail. If the
|
|
119
|
+
transaction fails due to a `WATCH` command, `EXEC` will return `None`.
|
|
119
120
|
|
|
120
|
-
|
|
121
|
+
**Retry and Redirection:**
|
|
121
122
|
|
|
122
123
|
- If a redirection error occurs:
|
|
123
|
-
- Atomic batches (Transactions)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
- **Atomic batches (Transactions):** The entire transaction will be
|
|
125
|
+
redirected.
|
|
126
|
+
- **Non-atomic batches:** Only commands that encountered redirection
|
|
127
|
+
errors will be redirected.
|
|
128
|
+
- Retries for failures will be handled according to the configured `BatchRetryStrategy`.
|
|
128
129
|
|
|
129
130
|
Args:
|
|
130
|
-
batch (ClusterBatch): A `ClusterBatch`
|
|
131
|
-
raise_on_error (bool): Determines how errors are handled within the batch response.
|
|
132
|
-
`True`, the first encountered error in the batch will be raised as
|
|
133
|
-
exception after all retries and reconnections have been
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
If a redirection error occurs:
|
|
141
|
-
- For Atomic Batches (Transactions), the entire transaction will be redirected.
|
|
142
|
-
- For Non-Atomic Batches (Pipelines), only the commands that encountered redirection errors
|
|
143
|
-
will be redirected.
|
|
144
|
-
timeout (Optional[int]): The duration in milliseconds that the client should wait for the batch request
|
|
145
|
-
to complete. This duration encompasses sending the request, awaiting a response from the server,
|
|
146
|
-
and any required reconnections or retries.
|
|
147
|
-
|
|
148
|
-
If the specified timeout is exceeded, a timeout error will be raised. If not explicitly set,
|
|
149
|
-
the client's default request timeout will be used.
|
|
150
|
-
retry_server_error (bool): If `True`, retriable server errors (e.g., `TRYAGAIN`) will trigger a retry.
|
|
151
|
-
Warning: Retrying server errors may cause commands targeting the same slot to execute out of order.
|
|
152
|
-
Note: Currently supported only for non-atomic batches. Recommended to increase timeout when enabled.
|
|
153
|
-
retry_connection_error (bool): If `True`, connection failures will trigger a retry. Warning:
|
|
154
|
-
Retrying connection errors may lead to duplicate executions, as it is unclear which commands have
|
|
155
|
-
already been processed. Note: Currently supported only for non-atomic batches. Recommended to increase
|
|
156
|
-
timeout when enabled.
|
|
131
|
+
batch (ClusterBatch): A `ClusterBatch` containing the commands to execute.
|
|
132
|
+
raise_on_error (bool): Determines how errors are handled within the batch response.
|
|
133
|
+
When set to `True`, the first encountered error in the batch will be raised as an
|
|
134
|
+
exception of type `RequestError` after all retries and reconnections have been
|
|
135
|
+
executed.
|
|
136
|
+
When set to `False`, errors will be included as part of the batch response,
|
|
137
|
+
allowing the caller to process both successful and failed commands together. In this case,
|
|
138
|
+
error details will be provided as instances of `RequestError`.
|
|
139
|
+
options (Optional[ClusterBatchOptions]): A `ClusterBatchOptions` object containing execution options.
|
|
157
140
|
|
|
158
141
|
Returns:
|
|
159
|
-
Optional[List[TResult]]:
|
|
160
|
-
|
|
161
|
-
the list entry will be `None`. If the batch failed due to a `WATCH` command, `exec` will return
|
|
162
|
-
`None`.
|
|
163
|
-
|
|
164
|
-
Examples:
|
|
165
|
-
# Example 1: Atomic Batch (Transaction)
|
|
166
|
-
>>> atomic_batch = ClusterBatch(is_atomic=True) # Atomic (Transaction)
|
|
167
|
-
>>> atomic_batch.set("key", "1")
|
|
168
|
-
>>> atomic_batch.incr("key")
|
|
169
|
-
>>> atomic_batch.get("key")
|
|
170
|
-
>>> atomic_result = await cluster_client.exec(atomic_batch, false)
|
|
171
|
-
>>> print(f"Atomic Batch Result: {atomic_result}")
|
|
172
|
-
# Expected Output: Atomic Batch Result: [OK, 2, 2]
|
|
142
|
+
Optional[List[TResult]]: An array of results, where each entry
|
|
143
|
+
corresponds to a command's execution result.
|
|
173
144
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
>>> non_atomic_batch.set("key2", "value2")
|
|
178
|
-
>>> non_atomic_batch.get("key1")
|
|
179
|
-
>>> non_atomic_batch.get("key2")
|
|
180
|
-
>>> non_atomic_result = await cluster_client.exec(non_atomic_batch, false)
|
|
181
|
-
>>> print(f"Non-Atomic Batch Result: {non_atomic_result}")
|
|
182
|
-
# Expected Output: Non-Atomic Batch Result: [OK, OK, value1, value2]
|
|
145
|
+
See Also:
|
|
146
|
+
[Valkey Transactions (Atomic Batches)](https://valkey.io/docs/topics/transactions/)
|
|
147
|
+
[Valkey Pipelines (Non-Atomic Batches)](https://valkey.io/docs/topics/pipelining/)
|
|
183
148
|
|
|
184
|
-
|
|
149
|
+
Examples:
|
|
150
|
+
# Atomic batch (transaction): all keys must share the same hash slot
|
|
151
|
+
>>> options = ClusterBatchOptions(timeout=1000) # Set a timeout of 1000 milliseconds
|
|
185
152
|
>>> atomic_batch = ClusterBatch(is_atomic=True)
|
|
186
153
|
>>> atomic_batch.set("key", "1")
|
|
187
154
|
>>> atomic_batch.incr("key")
|
|
188
155
|
>>> atomic_batch.get("key")
|
|
189
|
-
>>> atomic_result = await cluster_client.exec(
|
|
190
|
-
... atomic_batch,
|
|
191
|
-
... timeout=1000, # Set a timeout of 1000 milliseconds
|
|
192
|
-
... raise_on_error=False # Do not raise an error on failure
|
|
193
|
-
... )
|
|
156
|
+
>>> atomic_result = await cluster_client.exec(atomic_batch, False, options)
|
|
194
157
|
>>> print(f"Atomic Batch Result: {atomic_result}")
|
|
195
158
|
# Output: Atomic Batch Result: [OK, 2, 2]
|
|
196
159
|
|
|
197
|
-
#
|
|
160
|
+
# Non-atomic batch (pipeline): keys may span different hash slots
|
|
161
|
+
>>> retry_strategy = BatchRetryStrategy(retry_server_error=True, retry_connection_error=False)
|
|
162
|
+
>>> pipeline_options = ClusterBatchOptions(retry_strategy=retry_strategy)
|
|
198
163
|
>>> non_atomic_batch = ClusterBatch(is_atomic=False)
|
|
199
164
|
>>> non_atomic_batch.set("key1", "value1")
|
|
200
165
|
>>> non_atomic_batch.set("key2", "value2")
|
|
201
166
|
>>> non_atomic_batch.get("key1")
|
|
202
167
|
>>> non_atomic_batch.get("key2")
|
|
203
|
-
>>> non_atomic_result = await cluster_client.exec(
|
|
204
|
-
... non_atomic_batch,
|
|
205
|
-
... raise_on_error=False,
|
|
206
|
-
... retry_server_error=True,
|
|
207
|
-
... retry_connection_error=False
|
|
208
|
-
... )
|
|
168
|
+
>>> non_atomic_result = await cluster_client.exec(non_atomic_batch, False, pipeline_options)
|
|
209
169
|
>>> print(f"Non-Atomic Batch Result: {non_atomic_result}")
|
|
210
170
|
# Output: Non-Atomic Batch Result: [OK, OK, value1, value2]
|
|
211
171
|
"""
|
|
212
172
|
commands = batch.commands[:]
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
batch.is_atomic
|
|
176
|
+
and options
|
|
177
|
+
and options.retry_strategy
|
|
178
|
+
and (
|
|
179
|
+
options.retry_strategy.retry_server_error
|
|
180
|
+
or options.retry_strategy.retry_connection_error
|
|
181
|
+
)
|
|
182
|
+
):
|
|
183
|
+
raise RequestError(
|
|
184
|
+
"Retry strategies are not supported for atomic batches (transactions). "
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Extract values to make the _execute_batch call cleaner
|
|
188
|
+
retry_server_error = (
|
|
189
|
+
options.retry_strategy.retry_server_error
|
|
190
|
+
if options and options.retry_strategy
|
|
191
|
+
else False
|
|
192
|
+
)
|
|
193
|
+
retry_connection_error = (
|
|
194
|
+
options.retry_strategy.retry_connection_error
|
|
195
|
+
if options and options.retry_strategy
|
|
196
|
+
else False
|
|
197
|
+
)
|
|
198
|
+
route = options.route if options else None
|
|
199
|
+
timeout = options.timeout if options else None
|
|
200
|
+
|
|
213
201
|
return await self._execute_batch(
|
|
214
202
|
commands,
|
|
215
203
|
batch.is_atomic,
|
|
@@ -1078,11 +1066,17 @@ class ClusterCommands(CoreCommands):
|
|
|
1078
1066
|
self,
|
|
1079
1067
|
source: TEncodable,
|
|
1080
1068
|
destination: TEncodable,
|
|
1069
|
+
# TODO next major release the arguments replace and destinationDB must have their order
|
|
1070
|
+
# swapped to align with the standalone order.
|
|
1071
|
+
# At the moment of the patch release 2.1.1. we can't have a breaking change
|
|
1081
1072
|
replace: Optional[bool] = None,
|
|
1073
|
+
destinationDB: Optional[int] = None,
|
|
1082
1074
|
) -> bool:
|
|
1083
1075
|
"""
|
|
1084
|
-
Copies the value stored at the `source` to the `destination` key.
|
|
1085
|
-
|
|
1076
|
+
Copies the value stored at the `source` to the `destination` key. If `destinationDB`
|
|
1077
|
+
is specified, the value will be copied to the database specified by `destinationDB`,
|
|
1078
|
+
otherwise the current database will be used. When `replace` is True, removes the
|
|
1079
|
+
`destination` key first if it already exists, otherwise performs no action.
|
|
1086
1080
|
|
|
1087
1081
|
See [valkey.io](https://valkey.io/commands/copy) for more details.
|
|
1088
1082
|
|
|
@@ -1093,6 +1087,7 @@ class ClusterCommands(CoreCommands):
|
|
|
1093
1087
|
source (TEncodable): The key to the source value.
|
|
1094
1088
|
destination (TEncodable): The key where the value should be copied to.
|
|
1095
1089
|
replace (Optional[bool]): If the destination key should be removed before copying the value to it.
|
|
1090
|
+
destinationDB (Optional[int]): The alternative logical database index for the destination key.
|
|
1096
1091
|
|
|
1097
1092
|
Returns:
|
|
1098
1093
|
bool: True if the source was copied. Otherwise, returns False.
|
|
@@ -1101,12 +1096,20 @@ class ClusterCommands(CoreCommands):
|
|
|
1101
1096
|
>>> await client.set("source", "sheep")
|
|
1102
1097
|
>>> await client.copy(b"source", b"destination")
|
|
1103
1098
|
True # Source was copied
|
|
1099
|
+
>>> await client.copy(b"source", b"destination", destinationDB=1)
|
|
1100
|
+
True # Source was copied to DB 1
|
|
1101
|
+
>>> await client.select(1)
|
|
1104
1102
|
>>> await client.get("destination")
|
|
1105
1103
|
b"sheep"
|
|
1106
1104
|
|
|
1107
1105
|
Since: Valkey version 6.2.0.
|
|
1106
|
+
The destinationDB argument is available since Valkey 9.0.0
|
|
1108
1107
|
"""
|
|
1108
|
+
|
|
1109
|
+
# Build command arguments
|
|
1109
1110
|
args: List[TEncodable] = [source, destination]
|
|
1111
|
+
if destinationDB is not None:
|
|
1112
|
+
args.extend(["DB", str(destinationDB)])
|
|
1110
1113
|
if replace is True:
|
|
1111
1114
|
args.append("REPLACE")
|
|
1112
1115
|
return cast(
|
|
@@ -1153,7 +1156,7 @@ class ClusterCommands(CoreCommands):
|
|
|
1153
1156
|
args.extend(["VERSION", str(version)])
|
|
1154
1157
|
if parameters:
|
|
1155
1158
|
for var in parameters:
|
|
1156
|
-
args.
|
|
1159
|
+
args.append(str(var))
|
|
1157
1160
|
return cast(
|
|
1158
1161
|
TClusterResponse[bytes],
|
|
1159
1162
|
await self._execute_command(RequestType.Lolwut, args, route),
|
|
@@ -1433,7 +1436,7 @@ class ClusterCommands(CoreCommands):
|
|
|
1433
1436
|
|
|
1434
1437
|
Examples:
|
|
1435
1438
|
>>> lua_script = Script("return { KEYS[1], ARGV[1] }")
|
|
1436
|
-
>>> await client.invoke_script(lua_script, keys=["foo"], args=["bar"]
|
|
1439
|
+
>>> await client.invoke_script(lua_script, keys=["foo"], args=["bar"])
|
|
1437
1440
|
[b"foo", b"bar"]
|
|
1438
1441
|
"""
|
|
1439
1442
|
return await self._execute_script(script.get_hash(), keys, args)
|