valkey-glide 2.0.0rc7__cp310-cp310-macosx_11_0_arm64.whl → 2.1.0rc1__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.
Potentially problematic release.
This version of valkey-glide might be problematic. Click here for more details.
- glide/__init__.py +103 -107
- glide/async_commands/cluster_commands.py +83 -101
- glide/async_commands/core.py +554 -424
- 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 +18 -17
- glide/glide.cpython-310-darwin.so +0 -0
- glide/glide.pyi +26 -1
- glide/glide_client.py +70 -45
- glide/logger.py +33 -21
- glide/opentelemetry.py +185 -0
- glide_shared/__init__.py +326 -0
- {glide/async_commands → glide_shared/commands}/batch.py +411 -18
- 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 +120 -32
- {glide → glide_shared}/constants.py +3 -3
- {glide → glide_shared}/exceptions.py +27 -1
- glide_shared/protobuf/command_request_pb2.py +54 -0
- glide_shared/protobuf/connection_request_pb2.py +52 -0
- {glide → glide_shared}/protobuf/response_pb2.py +6 -6
- {glide → glide_shared}/routes.py +29 -15
- valkey_glide-2.1.0rc1.dist-info/METADATA +210 -0
- valkey_glide-2.1.0rc1.dist-info/RECORD +39 -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.0rc7.dist-info/METADATA +0 -144
- valkey_glide-2.0.0rc7.dist-info/RECORD +0 -37
- /glide/py.typed → /glide_shared/commands/__init__.py +0 -0
- {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.0rc7.dist-info → valkey_glide-2.1.0rc1.dist-info}/WHEEL +0 -0
|
@@ -5,24 +5,24 @@ module for `vector search` commands.
|
|
|
5
5
|
|
|
6
6
|
from typing import List, Mapping, Optional, cast
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from glide_shared.commands.server_modules.ft_options.ft_aggregate_options import (
|
|
9
9
|
FtAggregateOptions,
|
|
10
10
|
)
|
|
11
|
-
from
|
|
11
|
+
from glide_shared.commands.server_modules.ft_options.ft_constants import (
|
|
12
12
|
CommandNames,
|
|
13
13
|
FtCreateKeywords,
|
|
14
14
|
)
|
|
15
|
-
from
|
|
15
|
+
from glide_shared.commands.server_modules.ft_options.ft_create_options import (
|
|
16
16
|
Field,
|
|
17
17
|
FtCreateOptions,
|
|
18
18
|
)
|
|
19
|
-
from
|
|
19
|
+
from glide_shared.commands.server_modules.ft_options.ft_profile_options import (
|
|
20
20
|
FtProfileOptions,
|
|
21
21
|
)
|
|
22
|
-
from
|
|
22
|
+
from glide_shared.commands.server_modules.ft_options.ft_search_options import (
|
|
23
23
|
FtSearchOptions,
|
|
24
24
|
)
|
|
25
|
-
from
|
|
25
|
+
from glide_shared.constants import (
|
|
26
26
|
TOK,
|
|
27
27
|
FtAggregateResponse,
|
|
28
28
|
FtInfoResponse,
|
|
@@ -30,7 +30,8 @@ from glide.constants import (
|
|
|
30
30
|
FtSearchResponse,
|
|
31
31
|
TEncodable,
|
|
32
32
|
)
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
from ..glide_client import TGlideClient
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
async def create(
|
|
@@ -7,7 +7,7 @@ Examples:
|
|
|
7
7
|
>>> import json
|
|
8
8
|
>>> value = {'a': 1.0, 'b': 2}
|
|
9
9
|
>>> json_str = json.dumps(value) # Convert Python dictionary to JSON string using json.dumps()
|
|
10
|
-
>>> await
|
|
10
|
+
>>> await glide_json.set(client, "doc", "$", json_str)
|
|
11
11
|
'OK' # Indicates successful setting of the value at path '$' in the key stored at `doc`.
|
|
12
12
|
>>> json_get = await glide_json.get(client, "doc", "$") # Returns the value at path '$' in the JSON document stored at
|
|
13
13
|
# `doc` as JSON string.
|
|
@@ -19,97 +19,20 @@ Examples:
|
|
|
19
19
|
"""
|
|
20
20
|
from typing import List, Optional, Union, cast
|
|
21
21
|
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def __init__(
|
|
38
|
-
self,
|
|
39
|
-
indent: Optional[str] = None,
|
|
40
|
-
newline: Optional[str] = None,
|
|
41
|
-
space: Optional[str] = None,
|
|
42
|
-
):
|
|
43
|
-
self.indent = indent
|
|
44
|
-
self.new_line = newline
|
|
45
|
-
self.space = space
|
|
46
|
-
|
|
47
|
-
def get_options(self) -> List[str]:
|
|
48
|
-
args = []
|
|
49
|
-
if self.indent:
|
|
50
|
-
args.extend(["INDENT", self.indent])
|
|
51
|
-
if self.new_line:
|
|
52
|
-
args.extend(["NEWLINE", self.new_line])
|
|
53
|
-
if self.space:
|
|
54
|
-
args.extend(["SPACE", self.space])
|
|
55
|
-
return args
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class JsonArrIndexOptions:
|
|
59
|
-
"""
|
|
60
|
-
Options for the `JSON.ARRINDEX` command.
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
start (int): The inclusive start index from which the search begins. Defaults to None.
|
|
64
|
-
end (Optional[int]): The exclusive end index where the search stops. Defaults to None.
|
|
65
|
-
|
|
66
|
-
Note:
|
|
67
|
-
- If `start` is greater than `end`, the command returns `-1` to indicate that the value was not found.
|
|
68
|
-
- Indices that exceed the array bounds are automatically adjusted to the nearest valid position.
|
|
69
|
-
"""
|
|
70
|
-
|
|
71
|
-
def __init__(self, start: int, end: Optional[int] = None):
|
|
72
|
-
self.start = start
|
|
73
|
-
self.end = end
|
|
74
|
-
|
|
75
|
-
def to_args(self) -> List[str]:
|
|
76
|
-
"""
|
|
77
|
-
Get the options as a list of arguments for the JSON.ARRINDEX command.
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
List[str]: A list containing the start and end indices if specified.
|
|
81
|
-
"""
|
|
82
|
-
args = [str(self.start)]
|
|
83
|
-
if self.end is not None:
|
|
84
|
-
args.append(str(self.end))
|
|
85
|
-
return args
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class JsonArrPopOptions:
|
|
89
|
-
"""
|
|
90
|
-
Options for the JSON.ARRPOP command.
|
|
91
|
-
|
|
92
|
-
Args:
|
|
93
|
-
path (TEncodable): The path within the JSON document.
|
|
94
|
-
index (Optional[int]): The index of the element to pop. If not specified, will pop the last element.
|
|
95
|
-
Out of boundary indexes are rounded to their respective array boundaries. Defaults to None.
|
|
96
|
-
"""
|
|
97
|
-
|
|
98
|
-
def __init__(self, path: TEncodable, index: Optional[int] = None):
|
|
99
|
-
self.path = path
|
|
100
|
-
self.index = index
|
|
101
|
-
|
|
102
|
-
def to_args(self) -> List[TEncodable]:
|
|
103
|
-
"""
|
|
104
|
-
Get the options as a list of arguments for the `JSON.ARRPOP` command.
|
|
105
|
-
|
|
106
|
-
Returns:
|
|
107
|
-
List[TEncodable]: A list containing the path and, if specified, the index.
|
|
108
|
-
"""
|
|
109
|
-
args = [self.path]
|
|
110
|
-
if self.index is not None:
|
|
111
|
-
args.append(str(self.index))
|
|
112
|
-
return args
|
|
22
|
+
from glide_shared.commands.core_options import ConditionalChange
|
|
23
|
+
from glide_shared.commands.server_modules.json_options import (
|
|
24
|
+
JsonArrIndexOptions,
|
|
25
|
+
JsonArrPopOptions,
|
|
26
|
+
JsonGetOptions,
|
|
27
|
+
)
|
|
28
|
+
from glide_shared.constants import (
|
|
29
|
+
TOK,
|
|
30
|
+
TEncodable,
|
|
31
|
+
TJsonResponse,
|
|
32
|
+
TJsonUniversalResponse,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
from ..glide_client import TGlideClient
|
|
113
36
|
|
|
114
37
|
|
|
115
38
|
async def set(
|
|
@@ -4,24 +4,25 @@ 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 Script
|
|
8
|
+
from glide_shared.commands.batch import Batch
|
|
9
|
+
from glide_shared.commands.batch_options import BatchOptions
|
|
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
|
TEncodable,
|
|
18
19
|
TFunctionListResponse,
|
|
19
20
|
TFunctionStatsFullResponse,
|
|
20
21
|
TResult,
|
|
21
22
|
)
|
|
22
|
-
from
|
|
23
|
+
from glide_shared.protobuf.command_request_pb2 import RequestType
|
|
23
24
|
|
|
24
|
-
from
|
|
25
|
+
from .core import CoreCommands
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class StandaloneCommands(CoreCommands):
|
|
@@ -76,7 +77,7 @@ class StandaloneCommands(CoreCommands):
|
|
|
76
77
|
self,
|
|
77
78
|
batch: Batch,
|
|
78
79
|
raise_on_error: bool,
|
|
79
|
-
|
|
80
|
+
options: Optional[BatchOptions] = None,
|
|
80
81
|
) -> Optional[List[TResult]]:
|
|
81
82
|
"""
|
|
82
83
|
Executes a batch by processing the queued commands.
|
|
@@ -96,10 +97,7 @@ class StandaloneCommands(CoreCommands):
|
|
|
96
97
|
When set to ``False``, errors will be included as part of the batch response array, allowing
|
|
97
98
|
the caller to process both successful and failed commands together. In this case, error details
|
|
98
99
|
will be provided as instances of ``RequestError``.
|
|
99
|
-
|
|
100
|
-
to complete. This duration encompasses sending the request, awaiting a response from the server, and any
|
|
101
|
-
required reconnections or retries. If the specified timeout is exceeded for the request,
|
|
102
|
-
a timeout error will be raised. If not explicitly set, the client's default request timeout will be used.
|
|
100
|
+
options (Optional[BatchOptions]): A ``BatchOptions`` object containing execution options.
|
|
103
101
|
|
|
104
102
|
Returns:
|
|
105
103
|
Optional[List[TResult]]: An array of results, where each entry corresponds to a command's execution result.
|
|
@@ -125,33 +123,38 @@ class StandaloneCommands(CoreCommands):
|
|
|
125
123
|
# Expected Output: Pipeline Batch Result: [OK, OK, b'value1', b'value2']
|
|
126
124
|
|
|
127
125
|
Example (Atomic Batch - Transaction with options):
|
|
126
|
+
>>> from glide import BatchOptions
|
|
128
127
|
>>> transaction = Batch(is_atomic=True)
|
|
129
128
|
>>> transaction.set("key", "1")
|
|
130
129
|
>>> transaction.incr("key")
|
|
131
130
|
>>> transaction.custom_command(["get", "key"])
|
|
131
|
+
>>> options = BatchOptions(timeout=1000) # Set a timeout of 1000 milliseconds
|
|
132
132
|
>>> result = await client.exec(
|
|
133
133
|
... transaction,
|
|
134
134
|
... raise_on_error=False, # Do not raise an error on failure
|
|
135
|
-
...
|
|
135
|
+
... options=options
|
|
136
136
|
... )
|
|
137
137
|
>>> print(f"Transaction Result: {result}")
|
|
138
138
|
# Expected Output: Transaction Result: [OK, 2, b'2']
|
|
139
139
|
|
|
140
140
|
Example (Non-Atomic Batch - Pipeline with options):
|
|
141
|
+
>>> from glide import BatchOptions
|
|
141
142
|
>>> pipeline = Batch(is_atomic=False)
|
|
142
143
|
>>> pipeline.custom_command(["set", "key1", "value1"])
|
|
143
144
|
>>> pipeline.custom_command(["set", "key2", "value2"])
|
|
144
145
|
>>> pipeline.custom_command(["get", "key1"])
|
|
145
146
|
>>> pipeline.custom_command(["get", "key2"])
|
|
147
|
+
>>> options = BatchOptions(timeout=1000) # Set a timeout of 1000 milliseconds
|
|
146
148
|
>>> result = await client.exec(
|
|
147
149
|
... pipeline,
|
|
148
150
|
... raise_on_error=False, # Do not raise an error on failure
|
|
149
|
-
...
|
|
151
|
+
... options=options
|
|
150
152
|
... )
|
|
151
153
|
>>> print(f"Pipeline Result: {result}")
|
|
152
154
|
# Expected Output: Pipeline Result: [OK, OK, b'value1', b'value2']
|
|
153
155
|
"""
|
|
154
156
|
commands = batch.commands[:]
|
|
157
|
+
timeout = options.timeout if options else None
|
|
155
158
|
return await self._execute_batch(
|
|
156
159
|
commands,
|
|
157
160
|
is_atomic=batch.is_atomic,
|
|
@@ -868,8 +871,6 @@ class StandaloneCommands(CoreCommands):
|
|
|
868
871
|
TOK: A simple "OK" response.
|
|
869
872
|
|
|
870
873
|
Examples:
|
|
871
|
-
>>> await client.watch("sampleKey")
|
|
872
|
-
'OK'
|
|
873
874
|
>>> await client.unwatch()
|
|
874
875
|
'OK'
|
|
875
876
|
"""
|
|
@@ -1033,7 +1034,7 @@ class StandaloneCommands(CoreCommands):
|
|
|
1033
1034
|
|
|
1034
1035
|
Examples:
|
|
1035
1036
|
>>> lua_script = Script("return { KEYS[1], ARGV[1] }")
|
|
1036
|
-
>>> await client.invoke_script(lua_script, keys=["foo"], args=["bar"]
|
|
1037
|
+
>>> await client.invoke_script(lua_script, keys=["foo"], args=["bar"])
|
|
1037
1038
|
[b"foo", b"bar"]
|
|
1038
1039
|
"""
|
|
1039
1040
|
return await self._execute_script(script.get_hash(), keys, args)
|
|
Binary file
|
glide/glide.pyi
CHANGED
|
@@ -2,7 +2,7 @@ from collections.abc import Callable
|
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from typing import List, Optional, Union
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from glide_shared.constants import TResult
|
|
6
6
|
|
|
7
7
|
DEFAULT_TIMEOUT_IN_MILLISECONDS: int = ...
|
|
8
8
|
MAX_REQUEST_ARGS_LEN: int = ...
|
|
@@ -27,6 +27,28 @@ class ClusterScanCursor:
|
|
|
27
27
|
def get_cursor(self) -> str: ...
|
|
28
28
|
def is_finished(self) -> bool: ...
|
|
29
29
|
|
|
30
|
+
class OpenTelemetryConfig:
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
traces: Optional[OpenTelemetryTracesConfig] = None,
|
|
34
|
+
metrics: Optional[OpenTelemetryMetricsConfig] = None,
|
|
35
|
+
flush_interval_ms: Optional[int] = None,
|
|
36
|
+
) -> None: ...
|
|
37
|
+
def get_traces(self) -> Optional[OpenTelemetryTracesConfig]: ...
|
|
38
|
+
def set_traces(self, traces: OpenTelemetryTracesConfig) -> None: ...
|
|
39
|
+
def get_metrics(self) -> Optional[OpenTelemetryMetricsConfig]: ...
|
|
40
|
+
|
|
41
|
+
class OpenTelemetryTracesConfig:
|
|
42
|
+
def __init__(
|
|
43
|
+
self, endpoint: str, sample_percentage: Optional[int] = None
|
|
44
|
+
) -> None: ...
|
|
45
|
+
def get_endpoint(self) -> str: ...
|
|
46
|
+
def get_sample_percentage(self) -> Optional[int]: ...
|
|
47
|
+
|
|
48
|
+
class OpenTelemetryMetricsConfig:
|
|
49
|
+
def __init__(self, endpoint: str) -> None: ...
|
|
50
|
+
def get_endpoint(self) -> str: ...
|
|
51
|
+
|
|
30
52
|
def start_socket_listener_external(init_callback: Callable) -> None: ...
|
|
31
53
|
def value_from_pointer(pointer: int) -> TResult: ...
|
|
32
54
|
def create_leaked_value(message: str) -> int: ...
|
|
@@ -34,3 +56,6 @@ def create_leaked_bytes_vec(args_vec: List[bytes]) -> int: ...
|
|
|
34
56
|
def get_statistics() -> dict: ...
|
|
35
57
|
def py_init(level: Optional[Level], file_name: Optional[str]) -> Level: ...
|
|
36
58
|
def py_log(log_level: Level, log_identifier: str, message: str) -> None: ...
|
|
59
|
+
def create_otel_span(name: str) -> int: ...
|
|
60
|
+
def drop_otel_span(span_ptr: int) -> None: ...
|
|
61
|
+
def init_opentelemetry(config: OpenTelemetryConfig) -> None: ...
|
glide/glide_client.py
CHANGED
|
@@ -11,7 +11,6 @@ from typing import (
|
|
|
11
11
|
Optional,
|
|
12
12
|
Set,
|
|
13
13
|
Tuple,
|
|
14
|
-
Type,
|
|
15
14
|
Union,
|
|
16
15
|
cast,
|
|
17
16
|
)
|
|
@@ -19,38 +18,49 @@ from typing import (
|
|
|
19
18
|
import anyio
|
|
20
19
|
import sniffio
|
|
21
20
|
from anyio import to_thread
|
|
22
|
-
|
|
23
|
-
from glide.async_commands.cluster_commands import ClusterCommands
|
|
24
|
-
from glide.async_commands.command_args import ObjectType
|
|
25
|
-
from glide.async_commands.core import CoreCommands
|
|
26
|
-
from glide.async_commands.standalone_commands import StandaloneCommands
|
|
27
|
-
from glide.config import BaseClientConfiguration, ServerCredentials
|
|
28
|
-
from glide.constants import DEFAULT_READ_BYTES_SIZE, OK, TEncodable, TRequest, TResult
|
|
29
|
-
from glide.exceptions import (
|
|
30
|
-
ClosingError,
|
|
31
|
-
ConfigurationError,
|
|
32
|
-
ConnectionError,
|
|
33
|
-
ExecAbortError,
|
|
34
|
-
RequestError,
|
|
35
|
-
TimeoutError,
|
|
36
|
-
)
|
|
37
|
-
from glide.logger import Level as LogLevel
|
|
38
|
-
from glide.logger import Logger as ClientLogger
|
|
39
|
-
from glide.protobuf.command_request_pb2 import Command, CommandRequest, RequestType
|
|
40
|
-
from glide.protobuf.connection_request_pb2 import ConnectionRequest
|
|
41
|
-
from glide.protobuf.response_pb2 import RequestErrorType, Response
|
|
42
|
-
from glide.protobuf_codec import PartialMessageException, ProtobufCodec
|
|
43
|
-
from glide.routes import Route, set_protobuf_route
|
|
44
|
-
|
|
45
|
-
from .glide import (
|
|
21
|
+
from glide.glide import (
|
|
46
22
|
DEFAULT_TIMEOUT_IN_MILLISECONDS,
|
|
47
23
|
MAX_REQUEST_ARGS_LEN,
|
|
48
24
|
ClusterScanCursor,
|
|
49
25
|
create_leaked_bytes_vec,
|
|
26
|
+
create_otel_span,
|
|
27
|
+
drop_otel_span,
|
|
50
28
|
get_statistics,
|
|
51
29
|
start_socket_listener_external,
|
|
52
30
|
value_from_pointer,
|
|
53
31
|
)
|
|
32
|
+
from glide_shared.commands.command_args import ObjectType
|
|
33
|
+
from glide_shared.commands.core_options import PubSubMsg
|
|
34
|
+
from glide_shared.config import BaseClientConfiguration, ServerCredentials
|
|
35
|
+
from glide_shared.constants import (
|
|
36
|
+
DEFAULT_READ_BYTES_SIZE,
|
|
37
|
+
OK,
|
|
38
|
+
TEncodable,
|
|
39
|
+
TRequest,
|
|
40
|
+
TResult,
|
|
41
|
+
)
|
|
42
|
+
from glide_shared.exceptions import (
|
|
43
|
+
ClosingError,
|
|
44
|
+
ConfigurationError,
|
|
45
|
+
ConnectionError,
|
|
46
|
+
get_request_error_class,
|
|
47
|
+
)
|
|
48
|
+
from glide_shared.protobuf.command_request_pb2 import (
|
|
49
|
+
Command,
|
|
50
|
+
CommandRequest,
|
|
51
|
+
RequestType,
|
|
52
|
+
)
|
|
53
|
+
from glide_shared.protobuf.connection_request_pb2 import ConnectionRequest
|
|
54
|
+
from glide_shared.protobuf.response_pb2 import Response
|
|
55
|
+
from glide_shared.protobuf_codec import PartialMessageException, ProtobufCodec
|
|
56
|
+
from glide_shared.routes import Route, set_protobuf_route
|
|
57
|
+
|
|
58
|
+
from .async_commands.cluster_commands import ClusterCommands
|
|
59
|
+
from .async_commands.core import CoreCommands
|
|
60
|
+
from .async_commands.standalone_commands import StandaloneCommands
|
|
61
|
+
from .logger import Level as LogLevel
|
|
62
|
+
from .logger import Logger as ClientLogger
|
|
63
|
+
from .opentelemetry import OpenTelemetry
|
|
54
64
|
|
|
55
65
|
if sys.version_info >= (3, 11):
|
|
56
66
|
from typing import Self
|
|
@@ -66,20 +76,6 @@ if TYPE_CHECKING:
|
|
|
66
76
|
TFuture = Union[asyncio.Future[Any], "_CompatFuture"]
|
|
67
77
|
|
|
68
78
|
|
|
69
|
-
def get_request_error_class(
|
|
70
|
-
error_type: Optional[RequestErrorType.ValueType],
|
|
71
|
-
) -> Type[RequestError]:
|
|
72
|
-
if error_type == RequestErrorType.Disconnect:
|
|
73
|
-
return ConnectionError
|
|
74
|
-
if error_type == RequestErrorType.ExecAbort:
|
|
75
|
-
return ExecAbortError
|
|
76
|
-
if error_type == RequestErrorType.Timeout:
|
|
77
|
-
return TimeoutError
|
|
78
|
-
if error_type == RequestErrorType.Unspecified:
|
|
79
|
-
return RequestError
|
|
80
|
-
return RequestError
|
|
81
|
-
|
|
82
|
-
|
|
83
79
|
class _CompatFuture:
|
|
84
80
|
"""anyio shim for asyncio.Future-like functionality"""
|
|
85
81
|
|
|
@@ -410,6 +406,13 @@ class BaseClient(CoreCommands):
|
|
|
410
406
|
raise ClosingError(
|
|
411
407
|
"Unable to execute requests; the client is closed. Please create a new client."
|
|
412
408
|
)
|
|
409
|
+
|
|
410
|
+
# Create span if OpenTelemetry is configured and sampling indicates we should trace
|
|
411
|
+
span = None
|
|
412
|
+
if OpenTelemetry.should_sample():
|
|
413
|
+
command_name = RequestType.Name(request_type)
|
|
414
|
+
span = create_otel_span(command_name)
|
|
415
|
+
|
|
413
416
|
request = CommandRequest()
|
|
414
417
|
request.callback_idx = self._get_callback_index()
|
|
415
418
|
request.single_command.request_type = request_type
|
|
@@ -424,6 +427,11 @@ class BaseClient(CoreCommands):
|
|
|
424
427
|
request.single_command.args_vec_pointer = create_leaked_bytes_vec(
|
|
425
428
|
encoded_args
|
|
426
429
|
)
|
|
430
|
+
|
|
431
|
+
# Add span pointer to request if span was created
|
|
432
|
+
if span:
|
|
433
|
+
request.root_span_ptr = span
|
|
434
|
+
|
|
427
435
|
set_protobuf_route(request, route)
|
|
428
436
|
return await self._write_request_await_response(request)
|
|
429
437
|
|
|
@@ -441,6 +449,14 @@ class BaseClient(CoreCommands):
|
|
|
441
449
|
raise ClosingError(
|
|
442
450
|
"Unable to execute requests; the client is closed. Please create a new client."
|
|
443
451
|
)
|
|
452
|
+
|
|
453
|
+
# Create span if OpenTelemetry is configured and sampling indicates we should trace
|
|
454
|
+
span = None
|
|
455
|
+
|
|
456
|
+
if OpenTelemetry.should_sample():
|
|
457
|
+
# Use "Batch" as span name for batches
|
|
458
|
+
span = create_otel_span("Batch")
|
|
459
|
+
|
|
444
460
|
request = CommandRequest()
|
|
445
461
|
request.callback_idx = self._get_callback_index()
|
|
446
462
|
batch_commands = []
|
|
@@ -462,6 +478,11 @@ class BaseClient(CoreCommands):
|
|
|
462
478
|
request.batch.timeout = timeout
|
|
463
479
|
request.batch.retry_server_error = retry_server_error
|
|
464
480
|
request.batch.retry_connection_error = retry_connection_error
|
|
481
|
+
|
|
482
|
+
# Add span pointer to request if span was created
|
|
483
|
+
if span:
|
|
484
|
+
request.root_span_ptr = span
|
|
485
|
+
|
|
465
486
|
set_protobuf_route(request, route)
|
|
466
487
|
return await self._write_request_await_response(request)
|
|
467
488
|
|
|
@@ -496,7 +517,7 @@ class BaseClient(CoreCommands):
|
|
|
496
517
|
set_protobuf_route(request, route)
|
|
497
518
|
return await self._write_request_await_response(request)
|
|
498
519
|
|
|
499
|
-
async def get_pubsub_message(self) ->
|
|
520
|
+
async def get_pubsub_message(self) -> PubSubMsg:
|
|
500
521
|
if self._is_closed:
|
|
501
522
|
raise ClosingError(
|
|
502
523
|
"Unable to execute requests; the client is closed. Please create a new client."
|
|
@@ -523,7 +544,7 @@ class BaseClient(CoreCommands):
|
|
|
523
544
|
await response_future
|
|
524
545
|
return response_future.result()
|
|
525
546
|
|
|
526
|
-
def try_get_pubsub_message(self) -> Optional[
|
|
547
|
+
def try_get_pubsub_message(self) -> Optional[PubSubMsg]:
|
|
527
548
|
if self._is_closed:
|
|
528
549
|
raise ClosingError(
|
|
529
550
|
"Unable to execute requests; the client is closed. Please create a new client."
|
|
@@ -540,7 +561,7 @@ class BaseClient(CoreCommands):
|
|
|
540
561
|
)
|
|
541
562
|
|
|
542
563
|
# locking might not be required
|
|
543
|
-
msg: Optional[
|
|
564
|
+
msg: Optional[PubSubMsg] = None
|
|
544
565
|
try:
|
|
545
566
|
self._pubsub_lock.acquire()
|
|
546
567
|
self._complete_pubsub_futures_safe()
|
|
@@ -558,7 +579,7 @@ class BaseClient(CoreCommands):
|
|
|
558
579
|
|
|
559
580
|
def _notification_to_pubsub_message_safe(
|
|
560
581
|
self, response: Response
|
|
561
|
-
) -> Optional[
|
|
582
|
+
) -> Optional[PubSubMsg]:
|
|
562
583
|
pubsub_message = None
|
|
563
584
|
push_notification = cast(
|
|
564
585
|
Dict[str, Any], value_from_pointer(response.resp_pointer)
|
|
@@ -577,11 +598,11 @@ class BaseClient(CoreCommands):
|
|
|
577
598
|
):
|
|
578
599
|
values: List = push_notification["values"]
|
|
579
600
|
if message_kind == "PMessage":
|
|
580
|
-
pubsub_message =
|
|
601
|
+
pubsub_message = PubSubMsg(
|
|
581
602
|
message=values[2], channel=values[1], pattern=values[0]
|
|
582
603
|
)
|
|
583
604
|
else:
|
|
584
|
-
pubsub_message =
|
|
605
|
+
pubsub_message = PubSubMsg(
|
|
585
606
|
message=values[1], channel=values[0], pattern=None
|
|
586
607
|
)
|
|
587
608
|
elif (
|
|
@@ -656,6 +677,10 @@ class BaseClient(CoreCommands):
|
|
|
656
677
|
else:
|
|
657
678
|
res_future.set_result(None)
|
|
658
679
|
|
|
680
|
+
# Clean up span if it was created
|
|
681
|
+
if response.HasField("root_span_ptr"):
|
|
682
|
+
drop_otel_span(response.root_span_ptr)
|
|
683
|
+
|
|
659
684
|
async def _process_push(self, response: Response) -> None:
|
|
660
685
|
if response.HasField("closing_error") or not response.HasField("resp_pointer"):
|
|
661
686
|
err_msg = (
|
glide/logger.py
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import traceback
|
|
5
6
|
from enum import Enum
|
|
6
7
|
from typing import Optional
|
|
7
8
|
|
|
8
|
-
from .glide import Level as internalLevel
|
|
9
|
-
from .glide import py_init, py_log
|
|
9
|
+
from glide.glide import Level as internalLevel
|
|
10
|
+
from glide.glide import py_init, py_log
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class Level(Enum):
|
|
@@ -20,13 +21,12 @@ class Level(Enum):
|
|
|
20
21
|
|
|
21
22
|
class Logger:
|
|
22
23
|
"""
|
|
23
|
-
A singleton class that allows logging which is consistent with logs from the internal
|
|
24
|
+
A singleton class that allows logging which is consistent with logs from the internal GLIDE core.
|
|
24
25
|
The logger can be set up in 2 ways -
|
|
25
26
|
1. By calling Logger.init, which configures the logger only if it wasn't previously configured.
|
|
26
27
|
2. By calling Logger.set_logger_config, which replaces the existing configuration, and means that new logs will not be
|
|
27
28
|
saved with the logs that were sent before the call.
|
|
28
|
-
If
|
|
29
|
-
by the Rust core.
|
|
29
|
+
If none of these functions are called, the first log attempt will initialize a new logger with default configuration.
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
32
|
_instance = None
|
|
@@ -38,48 +38,60 @@ class Logger:
|
|
|
38
38
|
|
|
39
39
|
@classmethod
|
|
40
40
|
def init(cls, level: Optional[Level] = None, file_name: Optional[str] = None):
|
|
41
|
-
"""
|
|
41
|
+
"""
|
|
42
42
|
Initialize a logger if it wasn't initialized before - this method is meant to be used when there is no intention to
|
|
43
|
-
replace an existing logger.
|
|
44
|
-
The logger will filter all logs with a level lower than the given level
|
|
45
|
-
If given a
|
|
43
|
+
replace an existing logger. Otherwise, use `set_logger_config` for overriding the existing logger configs.
|
|
44
|
+
The logger will filter all logs with a level lower than the given level.
|
|
45
|
+
If given a file_name argument, will write the logs to files postfixed with file_name. If file_name isn't provided,
|
|
46
46
|
the logs will be written to the console.
|
|
47
|
+
|
|
47
48
|
Args:
|
|
48
49
|
level (Optional[Level]): Set the logger level to one of [ERROR, WARN, INFO, DEBUG, TRACE, OFF].
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
If log level isn't provided, the logger will be configured with default configuration.
|
|
51
|
+
To turn off logging completely, set the level to Level.OFF.
|
|
52
|
+
file_name (Optional[str]): If provided the target of the logs will be the file mentioned.
|
|
53
|
+
Otherwise, logs will be printed to the console.
|
|
53
54
|
"""
|
|
54
55
|
if cls._instance is None:
|
|
55
56
|
cls._instance = cls(level, file_name)
|
|
56
57
|
|
|
57
58
|
@classmethod
|
|
58
|
-
def log(
|
|
59
|
-
|
|
59
|
+
def log(
|
|
60
|
+
cls,
|
|
61
|
+
log_level: Level,
|
|
62
|
+
log_identifier: str,
|
|
63
|
+
message: str,
|
|
64
|
+
err: Optional[Exception] = None,
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
Logs the provided message if the provided log level is lower then the logger level.
|
|
60
68
|
|
|
61
69
|
Args:
|
|
62
|
-
log_level (Level): The log level of the provided message
|
|
70
|
+
log_level (Level): The log level of the provided message.
|
|
63
71
|
log_identifier (str): The log identifier should give the log a context.
|
|
64
72
|
message (str): The message to log.
|
|
73
|
+
err (Optional[Exception]): The exception or error to log.
|
|
65
74
|
"""
|
|
66
75
|
if not cls._instance:
|
|
67
76
|
cls._instance = cls(None)
|
|
68
77
|
if not log_level.value.is_lower(Logger.logger_level):
|
|
69
78
|
return
|
|
79
|
+
if err:
|
|
80
|
+
message = f"{message}: {traceback.format_exception(err)}"
|
|
70
81
|
py_log(log_level.value, log_identifier, message)
|
|
71
82
|
|
|
72
83
|
@classmethod
|
|
73
84
|
def set_logger_config(
|
|
74
85
|
cls, level: Optional[Level] = None, file_name: Optional[str] = None
|
|
75
86
|
):
|
|
76
|
-
"""
|
|
87
|
+
"""
|
|
88
|
+
Creates a new logger instance and configure it with the provided log level and file name.
|
|
77
89
|
|
|
78
90
|
Args:
|
|
79
91
|
level (Optional[Level]): Set the logger level to one of [ERROR, WARN, INFO, DEBUG, TRACE, OFF].
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
92
|
+
If log level isn't provided, the logger will be configured with default configuration.
|
|
93
|
+
To turn off logging completely, set the level to OFF.
|
|
94
|
+
file_name (Optional[str]): If provided the target of the logs will be the file mentioned.
|
|
95
|
+
Otherwise, logs will be printed to the console.
|
|
84
96
|
"""
|
|
85
97
|
Logger._instance = Logger(level, file_name)
|