kurrentdbclient 0.4__tar.gz → 1.0b2__tar.gz

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.
Files changed (50) hide show
  1. kurrentdbclient-0.4/README.md → kurrentdbclient-1.0b2/PKG-INFO +136 -26
  2. kurrentdbclient-0.4/PKG-INFO → kurrentdbclient-1.0b2/README.md +104 -56
  3. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/__init__.py +0 -2
  4. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/asyncio_client.py +62 -0
  5. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/client.py +64 -2
  6. kurrentdbclient-1.0b2/kurrentdbclient/instrumentation/opentelemetry/package.py +2 -0
  7. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/opentelemetry/version.py +1 -1
  8. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/projections.py +73 -10
  9. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/pyproject.toml +3 -3
  10. kurrentdbclient-0.4/kurrentdbclient/instrumentation/opentelemetry/package.py +0 -2
  11. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/LICENSE +0 -0
  12. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/common.py +0 -0
  13. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/connection.py +0 -0
  14. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/connection_spec.py +0 -0
  15. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/events.py +0 -0
  16. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/exceptions.py +0 -0
  17. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/gossip.py +0 -0
  18. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/__init__.py +0 -0
  19. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/opentelemetry/__init__.py +0 -0
  20. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/opentelemetry/attributes.py +0 -0
  21. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/opentelemetry/grpc.py +0 -0
  22. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/opentelemetry/spanners.py +0 -0
  23. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/instrumentation/opentelemetry/utils.py +0 -0
  24. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/persistent.py +0 -0
  25. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/cluster_pb2.py +0 -0
  26. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/cluster_pb2.pyi +0 -0
  27. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/cluster_pb2_grpc.py +0 -0
  28. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/code_pb2.py +0 -0
  29. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/code_pb2.pyi +0 -0
  30. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/code_pb2_grpc.py +0 -0
  31. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/gossip_pb2.py +0 -0
  32. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/gossip_pb2.pyi +0 -0
  33. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/gossip_pb2_grpc.py +0 -0
  34. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/persistent_pb2.py +0 -0
  35. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/persistent_pb2.pyi +0 -0
  36. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/persistent_pb2_grpc.py +0 -0
  37. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/projections_pb2.py +0 -0
  38. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/projections_pb2.pyi +0 -0
  39. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/projections_pb2_grpc.py +0 -0
  40. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/shared_pb2.py +0 -0
  41. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/shared_pb2.pyi +0 -0
  42. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/shared_pb2_grpc.py +0 -0
  43. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/status_pb2.py +0 -0
  44. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/status_pb2.pyi +0 -0
  45. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/status_pb2_grpc.py +0 -0
  46. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/streams_pb2.py +0 -0
  47. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/streams_pb2.pyi +0 -0
  48. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/protos/Grpc/streams_pb2_grpc.py +0 -0
  49. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/py.typed +0 -0
  50. {kurrentdbclient-0.4 → kurrentdbclient-1.0b2}/kurrentdbclient/streams.py +0 -0
@@ -1,3 +1,41 @@
1
+ Metadata-Version: 2.1
2
+ Name: kurrentdbclient
3
+ Version: 1.0b2
4
+ Summary: Python gRPC Client for KurrentDB
5
+ Home-page: https://github.com/pyeventsourcing/esdbclient
6
+ License: BSD 3-Clause
7
+ Author: John Bywater
8
+ Author-email: john.bywater@appropriatesoftware.net
9
+ Requires-Python: >=3.8,<4.0
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: License :: OSI Approved :: BSD License
12
+ Classifier: License :: Other/Proprietary License
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Provides-Extra: opentelemetry
22
+ Requires-Dist: grpcio (>=1.51.0,!=1.52.*,<1.69)
23
+ Requires-Dist: opentelemetry-api (>=1.28.0,<2.0.0) ; extra == "opentelemetry"
24
+ Requires-Dist: opentelemetry-instrumentation (>=0.49b0,<0.50) ; extra == "opentelemetry"
25
+ Requires-Dist: opentelemetry-semantic-conventions (>=0.49b0,<0.50) ; extra == "opentelemetry"
26
+ Requires-Dist: protobuf (>=3.11.0)
27
+ Requires-Dist: typing_extensions
28
+ Project-URL: Repository, https://github.com/pyeventsourcing/esdbclient
29
+ Description-Content-Type: text/markdown
30
+
31
+ <a href="https://kurrent.io">
32
+ <picture>
33
+ <source media="(prefers-color-scheme: dark)" srcset="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-White.png.png">
34
+ <source media="(prefers-color-scheme: light)" srcset="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-Black.png">
35
+ <img alt="Kurrent" src="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-Plum.png" height="50%" width="50%">
36
+ </picture>
37
+ </a>
38
+
1
39
  # Python gRPC Client for KurrentDB
2
40
 
3
41
  This [Python package](https://pypi.org/project/kurrentdbclient/) provides multithreaded and asyncio Python
@@ -7,13 +45,13 @@ The multithreaded `KurrentDBClient` is described in detail below. Please scroll
7
45
  down for <a href="#asyncio-client">information</a> about `AsyncKurrentDBClient`.
8
46
 
9
47
  These clients have been developed and are being maintained in a collaboration
10
- with the KurrentDB team, and are officially support by Kurrent Inc.
48
+ with the KurrentDB team, and are officially supported by Kurrent Inc.
11
49
  Although not all aspects of the KurrentDB gRPC API are implemented, most
12
50
  features are presented in an easy-to-use interface.
13
51
 
14
- These clients have been tested to work with KurrentDB LTS versions 22.10, 23.10,
15
- and 24.10, without and without SSL/TLS, with both single-server
16
- and cluster modes, and with Python versions 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13.
52
+ These clients have been tested to work with KurrentDB 25.0.0, without and without
53
+ SSL/TLS, with both single-server and cluster modes, and with Python versions
54
+ 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13.
17
55
 
18
56
  The test suite has 100% line and branch coverage. The code has typing annotations
19
57
  checked strictly with mypy. The code is formatted with black and isort, and checked
@@ -75,10 +113,13 @@ https://github.com/pyeventsourcing/eventsourcing-eventstoredb) package.
75
113
  * [Projections](#projections)
76
114
  * [Create projection](#create-projection)
77
115
  * [Get projection state](#get-projection-state)
78
- * [Get projection statistics](#get-projection-statistics)
79
116
  * [Update projection](#update-projection)
80
- * [Enable projection](#enable-projection)
117
+ * [Get projection statistics](#get-projection-statistics)
118
+ * [List all projection statistics](#list-all-projection-statistics)
119
+ * [List continuous projection statistics](#list-continuous-projection-statistics)
81
120
  * [Disable projection](#disable-projection)
121
+ * [Enable projection](#enable-projection)
122
+ * [Abort projection](#abort-projection)
82
123
  * [Reset projection](#reset-projection)
83
124
  * [Delete projection](#delete-projection)
84
125
  * [Restart projections subsystem](#restart-projections-subsystem)
@@ -287,7 +328,7 @@ The KurrentDB server can be run locally using the official Docker container imag
287
328
 
288
329
  For development, you can run a "secure" KurrentDB server using the following command.
289
330
 
290
- $ docker run -d --name kurrentdb-secure -it -p 2113:2113 --env "HOME=/tmp" docker.eventstore.com/eventstore/eventstoredb-ee:24.10.0-x64-8.0-bookworm-slim --dev
331
+ $ docker run -d --name kurrentdb-secure -it -p 2113:2113 --env "HOME=/tmp" docker.eventstore.com/kurrent-latest/kurrentdb:25.0.0-x64-8.0-bookworm-slim --dev
291
332
 
292
333
  As we will see, your client will need an KurrentDB connection string URI as the value
293
334
  of its `uri` constructor argument. The connection string for this "secure" KurrentDB
@@ -317,7 +358,7 @@ server_certificate = ssl.get_server_certificate(addr=('localhost', 2113))
317
358
 
318
359
  Alternatively, you can start an "insecure" server using the following command.
319
360
 
320
- $ docker run -d --name kurrentdb-insecure -it -p 2113:2113 docker.eventstore.com/eventstore/eventstoredb-ee:24.10.0-x64-8.0-bookworm-slim --insecure
361
+ $ docker run -d --name kurrentdb-insecure -it -p 2113:2113 docker.eventstore.com/kurrent-latest/kurrentdb:25.0.0-x64-8.0-bookworm-slim --insecure
321
362
 
322
363
  The connection string URI for this "insecure" server would be:
323
364
 
@@ -2992,6 +3033,41 @@ projection_state = client.get_projection_state(name=projection_name)
2992
3033
  assert projection_state.value == {'count': 3}
2993
3034
  ```
2994
3035
 
3036
+ ### Update projection<a id="update-projection"></a>
3037
+
3038
+ *requires leader*
3039
+
3040
+ The `update_projection()` method can be used to update a projection.
3041
+
3042
+ This method has two required arguments, `name` and `query`.
3043
+
3044
+ The required `name` argument is a Python `str` which specifies the name of the projection
3045
+ to be updated.
3046
+
3047
+ The required `query` argument is a Python `str` which defines what the projection will do.
3048
+
3049
+ This method also has three optional arguments, `emit_enabled`, `timeout`, and `credentials`.
3050
+
3051
+ The optional `emit_enabled` argument is a Python `bool` which specifies whether a
3052
+ projection will be able to emit events. If a `True` value is specified, the projection
3053
+ will be able to emit events. If a `False` value is specified, the projection will not
3054
+ be able to emit events. The default value of `emit_enabled` is `False`.
3055
+
3056
+ Please note, `emit_enabled` must be `True` if your projection query includes a call
3057
+ to `emit()`, otherwise the projection will not run.
3058
+
3059
+ Please note, it is not possible to update `track_emitted_streams` via the gRPC API.
3060
+
3061
+ The optional `timeout` argument is a Python `float` which sets a
3062
+ maximum duration, in seconds, for the completion of the gRPC operation.
3063
+
3064
+ The optional `credentials` argument can be used to
3065
+ override call credentials derived from the connection string URI.
3066
+
3067
+ ```python
3068
+ client.update_projection(name=projection_name, query=projection_query)
3069
+ ```
3070
+
2995
3071
  ### Get projection statistics<a id="get-projection-statistics"></a>
2996
3072
 
2997
3073
  *requires leader*
@@ -3019,30 +3095,35 @@ statistics = client.get_projection_statistics(name=projection_name)
3019
3095
  A `ProjectionStatistics` object is returned. The attributes of this object
3020
3096
  have values that represent the progress of the projection.
3021
3097
 
3022
- ### Update projection<a id="update-projection"></a>
3098
+
3099
+ ### List all projection statistics<a id="list-all-projection-statistics"></a>
3023
3100
 
3024
3101
  *requires leader*
3025
3102
 
3026
- The `update_projection()` method can be used to update a projection.
3103
+ The `list_all_projection_statistics()` method can be used to get a list of projection statistics for all projections.
3027
3104
 
3028
- This method has two required arguments, `name` and `query`.
3105
+ This method has two optional arguments, `timeout` and `credentials`.
3029
3106
 
3030
- The required `name` argument is a Python `str` which specifies the name of the projection
3031
- to be updated.
3107
+ The optional `timeout` argument is a Python `float` which sets a
3108
+ maximum duration, in seconds, for the completion of the gRPC operation.
3032
3109
 
3033
- The required `query` argument is a Python `str` which defines what the projection will do.
3110
+ The optional `credentials` argument can be used to
3111
+ override call credentials derived from the connection string URI.
3034
3112
 
3035
- This method also has three optional arguments, `emit_enabled`, `timeout`, and `credentials`.
3113
+ This method returns a list of `ProjectionStatistics` objects that each represent
3114
+ a projection.
3036
3115
 
3037
- The optional `emit_enabled` argument is a Python `bool` which specifies whether a
3038
- projection will be able to emit events. If a `True` value is specified, the projection
3039
- will be able to emit events. If a `False` value is specified, the projection will not
3040
- be able to emit events. The default value of `emit_enabled` is `False`.
3116
+ ```python
3117
+ statistics = client.list_all_projection_statistics()
3118
+ ```
3041
3119
 
3042
- Please note, `emit_enabled` must be `True` if your projection query includes a call
3043
- to `emit()`, otherwise the projection will not run.
3120
+ ### List continuous projection statistics<a id="list-continuous-projection-statistics"></a>
3044
3121
 
3045
- Please note, it is not possible to update `track_emitted_streams` via the gRPC API.
3122
+ *requires leader*
3123
+
3124
+ The `list_continuous_projection_statistics()` method can be used to get a list of projection statistics for all continuous projections.
3125
+
3126
+ This method has two optional arguments, `timeout` and `credentials`.
3046
3127
 
3047
3128
  The optional `timeout` argument is a Python `float` which sets a
3048
3129
  maximum duration, in seconds, for the completion of the gRPC operation.
@@ -3050,8 +3131,33 @@ maximum duration, in seconds, for the completion of the gRPC operation.
3050
3131
  The optional `credentials` argument can be used to
3051
3132
  override call credentials derived from the connection string URI.
3052
3133
 
3134
+ This method returns a list of `ProjectionStatistics` objects that each represent
3135
+ a projection.
3136
+
3053
3137
  ```python
3054
- client.update_projection(name=projection_name, query=projection_query)
3138
+ statistics = client.list_continuous_projection_statistics()
3139
+ ```
3140
+
3141
+ ### Disable projection<a id="disable-projection"></a>
3142
+
3143
+ *requires leader*
3144
+
3145
+ The `disable_projection()` method can be used to disable (stop running) a projection.
3146
+ When a projection is stopped using this method, a checkpoint will be written.
3147
+
3148
+ This method has a required `name` argument, which is a Python `str` that
3149
+ specifies the name of the projection to be disabled.
3150
+
3151
+ This method also has two optional arguments, `timeout`, and `credentials`.
3152
+
3153
+ The optional `timeout` argument is a Python `float` which sets a
3154
+ maximum duration, in seconds, for the completion of the gRPC operation.
3155
+
3156
+ The optional `credentials` argument can be used to
3157
+ override call credentials derived from the connection string URI.
3158
+
3159
+ ```python
3160
+ client.disable_projection(name=projection_name)
3055
3161
  ```
3056
3162
 
3057
3163
  ### Enable projection<a id="enable-projection"></a>
@@ -3076,11 +3182,13 @@ override call credentials derived from the connection string URI.
3076
3182
  client.enable_projection(name=projection_name)
3077
3183
  ```
3078
3184
 
3079
- ### Disable projection<a id="disable-projection"></a>
3185
+ ### Abort projection<a id="abort-projection"></a>
3080
3186
 
3081
3187
  *requires leader*
3082
3188
 
3083
- The `disable_projection()` method can be used to disable (stop running) a projection.
3189
+ The `abort_projection()` method can be used to abort (stop running) a projection.
3190
+ When a projection is stopped using this method, it will be stopped without writing
3191
+ a checkpoint.
3084
3192
 
3085
3193
  This method has a required `name` argument, which is a Python `str` that
3086
3194
  specifies the name of the projection to be disabled.
@@ -3094,7 +3202,7 @@ The optional `credentials` argument can be used to
3094
3202
  override call credentials derived from the connection string URI.
3095
3203
 
3096
3204
  ```python
3097
- client.disable_projection(name=projection_name)
3205
+ client.abort_projection(name=projection_name)
3098
3206
  ```
3099
3207
 
3100
3208
  ### Reset projection<a id="reset-projection"></a>
@@ -3159,6 +3267,7 @@ client.delete_projection(name=projection_name)
3159
3267
 
3160
3268
  Please note, a projection must be disabled before it can be deleted.
3161
3269
 
3270
+
3162
3271
  ### Restart projections subsystem<a id="restart-projections-subsystem"></a>
3163
3272
 
3164
3273
  *requires leader*
@@ -3736,3 +3845,4 @@ Update the `poetry.lock` file, and the project's virtual environment, using the
3736
3845
  following command.
3737
3846
 
3738
3847
  $ make update-packages
3848
+
@@ -1,32 +1,10 @@
1
- Metadata-Version: 2.1
2
- Name: kurrentdbclient
3
- Version: 0.4
4
- Summary: Python gRPC Client for KurrentDB
5
- Home-page: https://github.com/pyeventsourcing/esdbclient
6
- License: BSD 3-Clause
7
- Author: John Bywater
8
- Author-email: john.bywater@appropriatesoftware.net
9
- Requires-Python: >=3.8,<4.0
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: License :: OSI Approved :: BSD License
12
- Classifier: License :: Other/Proprietary License
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.8
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Programming Language :: Python :: 3.13
21
- Provides-Extra: opentelemetry
22
- Requires-Dist: grpcio (>=1.51.0,!=1.52.*,<1.69)
23
- Requires-Dist: opentelemetry-api (>=1.28.0,<2.0.0) ; extra == "opentelemetry"
24
- Requires-Dist: opentelemetry-instrumentation (>=0.49b0,<0.50) ; extra == "opentelemetry"
25
- Requires-Dist: opentelemetry-semantic-conventions (>=0.49b0,<0.50) ; extra == "opentelemetry"
26
- Requires-Dist: protobuf (>=3.11.0)
27
- Requires-Dist: typing_extensions
28
- Project-URL: Repository, https://github.com/pyeventsourcing/esdbclient
29
- Description-Content-Type: text/markdown
1
+ <a href="https://kurrent.io">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-White.png.png">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-Black.png">
5
+ <img alt="Kurrent" src="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-Plum.png" height="50%" width="50%">
6
+ </picture>
7
+ </a>
30
8
 
31
9
  # Python gRPC Client for KurrentDB
32
10
 
@@ -37,13 +15,13 @@ The multithreaded `KurrentDBClient` is described in detail below. Please scroll
37
15
  down for <a href="#asyncio-client">information</a> about `AsyncKurrentDBClient`.
38
16
 
39
17
  These clients have been developed and are being maintained in a collaboration
40
- with the KurrentDB team, and are officially support by Kurrent Inc.
18
+ with the KurrentDB team, and are officially supported by Kurrent Inc.
41
19
  Although not all aspects of the KurrentDB gRPC API are implemented, most
42
20
  features are presented in an easy-to-use interface.
43
21
 
44
- These clients have been tested to work with KurrentDB LTS versions 22.10, 23.10,
45
- and 24.10, without and without SSL/TLS, with both single-server
46
- and cluster modes, and with Python versions 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13.
22
+ These clients have been tested to work with KurrentDB 25.0.0, without and without
23
+ SSL/TLS, with both single-server and cluster modes, and with Python versions
24
+ 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13.
47
25
 
48
26
  The test suite has 100% line and branch coverage. The code has typing annotations
49
27
  checked strictly with mypy. The code is formatted with black and isort, and checked
@@ -105,10 +83,13 @@ https://github.com/pyeventsourcing/eventsourcing-eventstoredb) package.
105
83
  * [Projections](#projections)
106
84
  * [Create projection](#create-projection)
107
85
  * [Get projection state](#get-projection-state)
108
- * [Get projection statistics](#get-projection-statistics)
109
86
  * [Update projection](#update-projection)
110
- * [Enable projection](#enable-projection)
87
+ * [Get projection statistics](#get-projection-statistics)
88
+ * [List all projection statistics](#list-all-projection-statistics)
89
+ * [List continuous projection statistics](#list-continuous-projection-statistics)
111
90
  * [Disable projection](#disable-projection)
91
+ * [Enable projection](#enable-projection)
92
+ * [Abort projection](#abort-projection)
112
93
  * [Reset projection](#reset-projection)
113
94
  * [Delete projection](#delete-projection)
114
95
  * [Restart projections subsystem](#restart-projections-subsystem)
@@ -317,7 +298,7 @@ The KurrentDB server can be run locally using the official Docker container imag
317
298
 
318
299
  For development, you can run a "secure" KurrentDB server using the following command.
319
300
 
320
- $ docker run -d --name kurrentdb-secure -it -p 2113:2113 --env "HOME=/tmp" docker.eventstore.com/eventstore/eventstoredb-ee:24.10.0-x64-8.0-bookworm-slim --dev
301
+ $ docker run -d --name kurrentdb-secure -it -p 2113:2113 --env "HOME=/tmp" docker.eventstore.com/kurrent-latest/kurrentdb:25.0.0-x64-8.0-bookworm-slim --dev
321
302
 
322
303
  As we will see, your client will need an KurrentDB connection string URI as the value
323
304
  of its `uri` constructor argument. The connection string for this "secure" KurrentDB
@@ -347,7 +328,7 @@ server_certificate = ssl.get_server_certificate(addr=('localhost', 2113))
347
328
 
348
329
  Alternatively, you can start an "insecure" server using the following command.
349
330
 
350
- $ docker run -d --name kurrentdb-insecure -it -p 2113:2113 docker.eventstore.com/eventstore/eventstoredb-ee:24.10.0-x64-8.0-bookworm-slim --insecure
331
+ $ docker run -d --name kurrentdb-insecure -it -p 2113:2113 docker.eventstore.com/kurrent-latest/kurrentdb:25.0.0-x64-8.0-bookworm-slim --insecure
351
332
 
352
333
  The connection string URI for this "insecure" server would be:
353
334
 
@@ -3022,6 +3003,41 @@ projection_state = client.get_projection_state(name=projection_name)
3022
3003
  assert projection_state.value == {'count': 3}
3023
3004
  ```
3024
3005
 
3006
+ ### Update projection<a id="update-projection"></a>
3007
+
3008
+ *requires leader*
3009
+
3010
+ The `update_projection()` method can be used to update a projection.
3011
+
3012
+ This method has two required arguments, `name` and `query`.
3013
+
3014
+ The required `name` argument is a Python `str` which specifies the name of the projection
3015
+ to be updated.
3016
+
3017
+ The required `query` argument is a Python `str` which defines what the projection will do.
3018
+
3019
+ This method also has three optional arguments, `emit_enabled`, `timeout`, and `credentials`.
3020
+
3021
+ The optional `emit_enabled` argument is a Python `bool` which specifies whether a
3022
+ projection will be able to emit events. If a `True` value is specified, the projection
3023
+ will be able to emit events. If a `False` value is specified, the projection will not
3024
+ be able to emit events. The default value of `emit_enabled` is `False`.
3025
+
3026
+ Please note, `emit_enabled` must be `True` if your projection query includes a call
3027
+ to `emit()`, otherwise the projection will not run.
3028
+
3029
+ Please note, it is not possible to update `track_emitted_streams` via the gRPC API.
3030
+
3031
+ The optional `timeout` argument is a Python `float` which sets a
3032
+ maximum duration, in seconds, for the completion of the gRPC operation.
3033
+
3034
+ The optional `credentials` argument can be used to
3035
+ override call credentials derived from the connection string URI.
3036
+
3037
+ ```python
3038
+ client.update_projection(name=projection_name, query=projection_query)
3039
+ ```
3040
+
3025
3041
  ### Get projection statistics<a id="get-projection-statistics"></a>
3026
3042
 
3027
3043
  *requires leader*
@@ -3049,30 +3065,35 @@ statistics = client.get_projection_statistics(name=projection_name)
3049
3065
  A `ProjectionStatistics` object is returned. The attributes of this object
3050
3066
  have values that represent the progress of the projection.
3051
3067
 
3052
- ### Update projection<a id="update-projection"></a>
3068
+
3069
+ ### List all projection statistics<a id="list-all-projection-statistics"></a>
3053
3070
 
3054
3071
  *requires leader*
3055
3072
 
3056
- The `update_projection()` method can be used to update a projection.
3073
+ The `list_all_projection_statistics()` method can be used to get a list of projection statistics for all projections.
3057
3074
 
3058
- This method has two required arguments, `name` and `query`.
3075
+ This method has two optional arguments, `timeout` and `credentials`.
3059
3076
 
3060
- The required `name` argument is a Python `str` which specifies the name of the projection
3061
- to be updated.
3077
+ The optional `timeout` argument is a Python `float` which sets a
3078
+ maximum duration, in seconds, for the completion of the gRPC operation.
3062
3079
 
3063
- The required `query` argument is a Python `str` which defines what the projection will do.
3080
+ The optional `credentials` argument can be used to
3081
+ override call credentials derived from the connection string URI.
3064
3082
 
3065
- This method also has three optional arguments, `emit_enabled`, `timeout`, and `credentials`.
3083
+ This method returns a list of `ProjectionStatistics` objects that each represent
3084
+ a projection.
3066
3085
 
3067
- The optional `emit_enabled` argument is a Python `bool` which specifies whether a
3068
- projection will be able to emit events. If a `True` value is specified, the projection
3069
- will be able to emit events. If a `False` value is specified, the projection will not
3070
- be able to emit events. The default value of `emit_enabled` is `False`.
3086
+ ```python
3087
+ statistics = client.list_all_projection_statistics()
3088
+ ```
3071
3089
 
3072
- Please note, `emit_enabled` must be `True` if your projection query includes a call
3073
- to `emit()`, otherwise the projection will not run.
3090
+ ### List continuous projection statistics<a id="list-continuous-projection-statistics"></a>
3074
3091
 
3075
- Please note, it is not possible to update `track_emitted_streams` via the gRPC API.
3092
+ *requires leader*
3093
+
3094
+ The `list_continuous_projection_statistics()` method can be used to get a list of projection statistics for all continuous projections.
3095
+
3096
+ This method has two optional arguments, `timeout` and `credentials`.
3076
3097
 
3077
3098
  The optional `timeout` argument is a Python `float` which sets a
3078
3099
  maximum duration, in seconds, for the completion of the gRPC operation.
@@ -3080,8 +3101,33 @@ maximum duration, in seconds, for the completion of the gRPC operation.
3080
3101
  The optional `credentials` argument can be used to
3081
3102
  override call credentials derived from the connection string URI.
3082
3103
 
3104
+ This method returns a list of `ProjectionStatistics` objects that each represent
3105
+ a projection.
3106
+
3083
3107
  ```python
3084
- client.update_projection(name=projection_name, query=projection_query)
3108
+ statistics = client.list_continuous_projection_statistics()
3109
+ ```
3110
+
3111
+ ### Disable projection<a id="disable-projection"></a>
3112
+
3113
+ *requires leader*
3114
+
3115
+ The `disable_projection()` method can be used to disable (stop running) a projection.
3116
+ When a projection is stopped using this method, a checkpoint will be written.
3117
+
3118
+ This method has a required `name` argument, which is a Python `str` that
3119
+ specifies the name of the projection to be disabled.
3120
+
3121
+ This method also has two optional arguments, `timeout`, and `credentials`.
3122
+
3123
+ The optional `timeout` argument is a Python `float` which sets a
3124
+ maximum duration, in seconds, for the completion of the gRPC operation.
3125
+
3126
+ The optional `credentials` argument can be used to
3127
+ override call credentials derived from the connection string URI.
3128
+
3129
+ ```python
3130
+ client.disable_projection(name=projection_name)
3085
3131
  ```
3086
3132
 
3087
3133
  ### Enable projection<a id="enable-projection"></a>
@@ -3106,11 +3152,13 @@ override call credentials derived from the connection string URI.
3106
3152
  client.enable_projection(name=projection_name)
3107
3153
  ```
3108
3154
 
3109
- ### Disable projection<a id="disable-projection"></a>
3155
+ ### Abort projection<a id="abort-projection"></a>
3110
3156
 
3111
3157
  *requires leader*
3112
3158
 
3113
- The `disable_projection()` method can be used to disable (stop running) a projection.
3159
+ The `abort_projection()` method can be used to abort (stop running) a projection.
3160
+ When a projection is stopped using this method, it will be stopped without writing
3161
+ a checkpoint.
3114
3162
 
3115
3163
  This method has a required `name` argument, which is a Python `str` that
3116
3164
  specifies the name of the projection to be disabled.
@@ -3124,7 +3172,7 @@ The optional `credentials` argument can be used to
3124
3172
  override call credentials derived from the connection string URI.
3125
3173
 
3126
3174
  ```python
3127
- client.disable_projection(name=projection_name)
3175
+ client.abort_projection(name=projection_name)
3128
3176
  ```
3129
3177
 
3130
3178
  ### Reset projection<a id="reset-projection"></a>
@@ -3189,6 +3237,7 @@ client.delete_projection(name=projection_name)
3189
3237
 
3190
3238
  Please note, a projection must be disabled before it can be deleted.
3191
3239
 
3240
+
3192
3241
  ### Restart projections subsystem<a id="restart-projections-subsystem"></a>
3193
3242
 
3194
3243
  *requires leader*
@@ -3766,4 +3815,3 @@ Update the `poetry.lock` file, and the project's virtual environment, using the
3766
3815
  following command.
3767
3816
 
3768
3817
  $ make update-packages
3769
-
@@ -25,8 +25,6 @@ from kurrentdbclient.streams import (
25
25
  StreamState,
26
26
  )
27
27
 
28
- __version__ = "1.1"
29
-
30
28
  __all__ = [
31
29
  "DEFAULT_EXCLUDE_FILTER",
32
30
  "KDB_PERSISTENT_CONFIG_EVENTS_REGEX",
@@ -11,6 +11,7 @@ from typing import (
11
11
  Callable,
12
12
  Dict,
13
13
  Iterable,
14
+ List,
14
15
  Optional,
15
16
  Sequence,
16
17
  Tuple,
@@ -1512,6 +1513,45 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
1512
1513
  credentials=credentials or self._call_credentials,
1513
1514
  )
1514
1515
 
1516
+ @retrygrpc
1517
+ @autoreconnect
1518
+ async def list_continuous_projection_statistics(
1519
+ self,
1520
+ *,
1521
+ timeout: Optional[float] = None,
1522
+ credentials: Optional[grpc.CallCredentials] = None,
1523
+ ) -> List[ProjectionStatistics]:
1524
+ """
1525
+ Lists statistics for continuous projections.
1526
+ """
1527
+ timeout = timeout if timeout is not None else self._default_deadline
1528
+
1529
+ return await self._connection.projections.list_statistics(
1530
+ timeout=timeout,
1531
+ metadata=self._call_metadata,
1532
+ credentials=credentials or self._call_credentials,
1533
+ )
1534
+
1535
+ @retrygrpc
1536
+ @autoreconnect
1537
+ async def list_all_projection_statistics(
1538
+ self,
1539
+ *,
1540
+ timeout: Optional[float] = None,
1541
+ credentials: Optional[grpc.CallCredentials] = None,
1542
+ ) -> List[ProjectionStatistics]:
1543
+ """
1544
+ Lists statistics for all projections.
1545
+ """
1546
+ timeout = timeout if timeout is not None else self._default_deadline
1547
+
1548
+ return await self._connection.projections.list_statistics(
1549
+ all=True,
1550
+ timeout=timeout,
1551
+ metadata=self._call_metadata,
1552
+ credentials=credentials or self._call_credentials,
1553
+ )
1554
+
1515
1555
  @retrygrpc
1516
1556
  @autoreconnect
1517
1557
  async def disable_projection(
@@ -1534,6 +1574,28 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
1534
1574
  credentials=credentials or self._call_credentials,
1535
1575
  )
1536
1576
 
1577
+ @retrygrpc
1578
+ @autoreconnect
1579
+ async def abort_projection(
1580
+ self,
1581
+ name: str,
1582
+ *,
1583
+ timeout: Optional[float] = None,
1584
+ credentials: Optional[grpc.CallCredentials] = None,
1585
+ ) -> None:
1586
+ """
1587
+ Aborts a projection.
1588
+ """
1589
+ timeout = timeout if timeout is not None else self._default_deadline
1590
+
1591
+ await self._connection.projections.disable(
1592
+ name=name,
1593
+ write_checkpoint=False,
1594
+ timeout=timeout,
1595
+ metadata=self._call_metadata,
1596
+ credentials=credentials or self._call_credentials,
1597
+ )
1598
+
1537
1599
  @retrygrpc
1538
1600
  @autoreconnect
1539
1601
  async def enable_projection(
@@ -13,6 +13,7 @@ from typing import (
13
13
  Callable,
14
14
  Dict,
15
15
  Iterable,
16
+ List,
16
17
  Optional,
17
18
  Sequence,
18
19
  Tuple,
@@ -1752,7 +1753,7 @@ class KurrentDBClient(BaseKurrentDBClient):
1752
1753
  credentials: Optional[grpc.CallCredentials] = None,
1753
1754
  ) -> ProjectionStatistics:
1754
1755
  """
1755
- Gets projection statistics.
1756
+ Gets statistics for named projection.
1756
1757
  """
1757
1758
  timeout = timeout if timeout is not None else self._default_deadline
1758
1759
 
@@ -1763,6 +1764,45 @@ class KurrentDBClient(BaseKurrentDBClient):
1763
1764
  credentials=credentials or self._call_credentials,
1764
1765
  )
1765
1766
 
1767
+ @retrygrpc
1768
+ @autoreconnect
1769
+ def list_continuous_projection_statistics(
1770
+ self,
1771
+ *,
1772
+ timeout: Optional[float] = None,
1773
+ credentials: Optional[grpc.CallCredentials] = None,
1774
+ ) -> List[ProjectionStatistics]:
1775
+ """
1776
+ Lists statistics for continuous projections.
1777
+ """
1778
+ timeout = timeout if timeout is not None else self._default_deadline
1779
+
1780
+ return self.projections.list_statistics(
1781
+ timeout=timeout,
1782
+ metadata=self._call_metadata,
1783
+ credentials=credentials or self._call_credentials,
1784
+ )
1785
+
1786
+ @retrygrpc
1787
+ @autoreconnect
1788
+ def list_all_projection_statistics(
1789
+ self,
1790
+ *,
1791
+ timeout: Optional[float] = None,
1792
+ credentials: Optional[grpc.CallCredentials] = None,
1793
+ ) -> List[ProjectionStatistics]:
1794
+ """
1795
+ Lists statistics for all projections.
1796
+ """
1797
+ timeout = timeout if timeout is not None else self._default_deadline
1798
+
1799
+ return self.projections.list_statistics(
1800
+ all=True,
1801
+ timeout=timeout,
1802
+ metadata=self._call_metadata,
1803
+ credentials=credentials or self._call_credentials,
1804
+ )
1805
+
1766
1806
  @retrygrpc
1767
1807
  @autoreconnect
1768
1808
  def disable_projection(
@@ -1785,6 +1825,28 @@ class KurrentDBClient(BaseKurrentDBClient):
1785
1825
  credentials=credentials or self._call_credentials,
1786
1826
  )
1787
1827
 
1828
+ @retrygrpc
1829
+ @autoreconnect
1830
+ def abort_projection(
1831
+ self,
1832
+ name: str,
1833
+ *,
1834
+ timeout: Optional[float] = None,
1835
+ credentials: Optional[grpc.CallCredentials] = None,
1836
+ ) -> None:
1837
+ """
1838
+ Aborts a projection.
1839
+ """
1840
+ timeout = timeout if timeout is not None else self._default_deadline
1841
+
1842
+ self.projections.disable(
1843
+ name=name,
1844
+ write_checkpoint=False,
1845
+ timeout=timeout,
1846
+ metadata=self._call_metadata,
1847
+ credentials=credentials or self._call_credentials,
1848
+ )
1849
+
1788
1850
  @retrygrpc
1789
1851
  @autoreconnect
1790
1852
  def enable_projection(
@@ -1795,7 +1857,7 @@ class KurrentDBClient(BaseKurrentDBClient):
1795
1857
  credentials: Optional[grpc.CallCredentials] = None,
1796
1858
  ) -> None:
1797
1859
  """
1798
- Disables a projection.
1860
+ Enables a projection.
1799
1861
  """
1800
1862
  timeout = timeout if timeout is not None else self._default_deadline
1801
1863
 
@@ -0,0 +1,2 @@
1
+ # -*- coding: utf-8 -*-
2
+ _instruments = (f"{__name__.split('.')[0]} == 1.0b2",)
@@ -1,2 +1,2 @@
1
1
  # -*- coding: utf-8 -*-
2
- __version__ = "1.1"
2
+ __version__ = "1.0"
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
+ from __future__ import annotations
3
+
2
4
  from dataclasses import dataclass
3
- from typing import Any, Optional, Union
5
+ from typing import Any, List, Optional, Union
4
6
 
5
7
  import grpc
6
8
  import grpc.aio
@@ -51,11 +53,6 @@ class ProjectionState:
51
53
  value: Any
52
54
 
53
55
 
54
- @dataclass(frozen=True)
55
- class ProjectionResult:
56
- value: Any
57
-
58
-
59
56
  class BaseProjectionsService(KurrentDBService[TGrpcStreamers]):
60
57
  def __init__(
61
58
  self,
@@ -115,11 +112,21 @@ class BaseProjectionsService(KurrentDBService[TGrpcStreamers]):
115
112
 
116
113
  @staticmethod
117
114
  def _construct_statistics_req(
118
- name: str,
115
+ *,
116
+ name: str | None = None,
117
+ all: bool = False,
119
118
  ) -> projections_pb2.StatisticsReq:
120
- return projections_pb2.StatisticsReq(
121
- options=projections_pb2.StatisticsReq.Options(name=name),
122
- )
119
+ if name is not None:
120
+ options = projections_pb2.StatisticsReq.Options(name=name)
121
+ elif all:
122
+ options = projections_pb2.StatisticsReq.Options(
123
+ all=shared_pb2.Empty(),
124
+ )
125
+ else:
126
+ options = projections_pb2.StatisticsReq.Options(
127
+ continuous=shared_pb2.Empty(),
128
+ )
129
+ return projections_pb2.StatisticsReq(options=options)
123
130
 
124
131
  @staticmethod
125
132
  def _construct_disable_req(
@@ -351,6 +358,34 @@ class AsyncProjectionsService(BaseProjectionsService[AsyncGrpcStreamers]):
351
358
  except grpc.RpcError as e:
352
359
  raise handle_rpc_error(e) from None
353
360
 
361
+ async def list_statistics(
362
+ self,
363
+ all: bool = False,
364
+ timeout: Optional[float] = None,
365
+ metadata: Optional[Metadata] = None,
366
+ credentials: Optional[grpc.CallCredentials] = None,
367
+ ) -> List[ProjectionStatistics]: # pragma: no cover
368
+ statistics_req = self._construct_statistics_req(all=all)
369
+ try:
370
+ statistics_resps = self._stub.Statistics(
371
+ statistics_req,
372
+ timeout=timeout,
373
+ metadata=self._metadata(metadata, requires_leader=True),
374
+ credentials=credentials,
375
+ )
376
+ list_of_projection_statistics = []
377
+ async for statistics_resp in statistics_resps:
378
+ assert isinstance(
379
+ statistics_resp, projections_pb2.StatisticsResp
380
+ ), statistics_resp
381
+ projection_statistics = self._construct_projection_statistics(
382
+ statistics_resp
383
+ )
384
+ list_of_projection_statistics.append(projection_statistics)
385
+ return list_of_projection_statistics
386
+ except grpc.RpcError as e:
387
+ raise handle_rpc_error(e) from None
388
+
354
389
  async def disable(
355
390
  self,
356
391
  name: str,
@@ -600,6 +635,34 @@ class ProjectionsService(BaseProjectionsService[GrpcStreamers]):
600
635
  except grpc.RpcError as e:
601
636
  raise handle_rpc_error(e) from None
602
637
 
638
+ def list_statistics(
639
+ self,
640
+ all: bool = False,
641
+ timeout: Optional[float] = None,
642
+ metadata: Optional[Metadata] = None,
643
+ credentials: Optional[grpc.CallCredentials] = None,
644
+ ) -> List[ProjectionStatistics]: # pragma: no cover
645
+ statistics_req = self._construct_statistics_req(all=all)
646
+ try:
647
+ statistics_resps = self._stub.Statistics(
648
+ statistics_req,
649
+ timeout=timeout,
650
+ metadata=self._metadata(metadata, requires_leader=True),
651
+ credentials=credentials,
652
+ )
653
+ list_of_projection_statistics = []
654
+ for statistics_resp in statistics_resps:
655
+ assert isinstance(
656
+ statistics_resp, projections_pb2.StatisticsResp
657
+ ), statistics_resp
658
+ projection_statistics = self._construct_projection_statistics(
659
+ statistics_resp
660
+ )
661
+ list_of_projection_statistics.append(projection_statistics)
662
+ return list_of_projection_statistics
663
+ except grpc.RpcError as e:
664
+ raise handle_rpc_error(e) from None
665
+
603
666
  def disable(
604
667
  self,
605
668
  name: str,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "kurrentdbclient"
3
- version = "0.4"
3
+ version = "1.0b2"
4
4
 
5
5
  description = "Python gRPC Client for KurrentDB"
6
6
  authors = [
@@ -8,8 +8,8 @@ authors = [
8
8
  ]
9
9
  license = "BSD 3-Clause"
10
10
  classifiers = [
11
- "Development Status :: 3 - Alpha",
12
- # "Development Status :: 4 - Beta",
11
+ # "Development Status :: 3 - Alpha",
12
+ "Development Status :: 4 - Beta",
13
13
  # "Development Status :: 5 - Production/Stable",
14
14
  "License :: OSI Approved :: BSD License",
15
15
  "Programming Language :: Python :: 3",
@@ -1,2 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- _instruments = (f"{__name__.split('.')[0]} >= 0.1",)
File without changes