kurrentdbclient 1.1.2__tar.gz → 1.2__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 (63) hide show
  1. kurrentdbclient-1.1.2/README.md → kurrentdbclient-1.2/PKG-INFO +103 -2
  2. kurrentdbclient-1.1.2/PKG-INFO → kurrentdbclient-1.2/README.md +71 -32
  3. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/__init__.py +1 -1
  4. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/asyncio_client.py +53 -4
  5. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/client.py +112 -9
  6. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/common.py +46 -64
  7. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/connection.py +8 -2
  8. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/connection_spec.py +4 -2
  9. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/events.py +10 -10
  10. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/grpc.py +52 -51
  11. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/spanners.py +2 -2
  12. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/utils.py +4 -5
  13. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/persistent.py +39 -22
  14. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/streams.py +22 -7
  15. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/unpack_error_status.py +2 -1
  16. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/v2streams.py +2 -2
  17. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/pyproject.toml +7 -7
  18. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/LICENSE +0 -0
  19. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/exceptions.py +0 -0
  20. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/gossip.py +0 -0
  21. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/__init__.py +0 -0
  22. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/__init__.py +0 -0
  23. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/attributes.py +0 -0
  24. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/package.py +0 -0
  25. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/instrumentation/opentelemetry/version.py +0 -0
  26. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/projections.py +0 -0
  27. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/google/rpc/code_pb2.py +0 -0
  28. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/google/rpc/code_pb2.pyi +0 -0
  29. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/google/rpc/code_pb2_grpc.py +0 -0
  30. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/kurrent/rpc/errors_pb2.py +0 -0
  31. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/kurrent/rpc/errors_pb2.pyi +0 -0
  32. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/kurrent/rpc/errors_pb2_grpc.py +0 -0
  33. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/kurrent/rpc/rpc_pb2.py +0 -0
  34. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/kurrent/rpc/rpc_pb2.pyi +0 -0
  35. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/kurrent/rpc/rpc_pb2_grpc.py +0 -0
  36. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/cluster_pb2.py +0 -0
  37. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/cluster_pb2.pyi +0 -0
  38. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/cluster_pb2_grpc.py +0 -0
  39. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/gossip_pb2.py +0 -0
  40. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/gossip_pb2.pyi +0 -0
  41. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/gossip_pb2_grpc.py +0 -0
  42. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/persistent_pb2.py +0 -0
  43. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/persistent_pb2.pyi +0 -0
  44. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/persistent_pb2_grpc.py +0 -0
  45. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/projections_pb2.py +0 -0
  46. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/projections_pb2.pyi +0 -0
  47. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/projections_pb2_grpc.py +0 -0
  48. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/shared_pb2.py +0 -0
  49. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/shared_pb2.pyi +0 -0
  50. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/shared_pb2_grpc.py +0 -0
  51. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/status_pb2.py +0 -0
  52. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/status_pb2.pyi +0 -0
  53. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/status_pb2_grpc.py +0 -0
  54. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/streams_pb2.py +0 -0
  55. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/streams_pb2.pyi +0 -0
  56. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v1/streams_pb2_grpc.py +0 -0
  57. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v2/streams/errors_pb2.py +0 -0
  58. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v2/streams/errors_pb2.pyi +0 -0
  59. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v2/streams/errors_pb2_grpc.py +0 -0
  60. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v2/streams/streams_pb2.py +0 -0
  61. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v2/streams/streams_pb2.pyi +0 -0
  62. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/protos/v2/streams/streams_pb2_grpc.py +0 -0
  63. {kurrentdbclient-1.1.2 → kurrentdbclient-1.2}/kurrentdbclient/py.typed +0 -0
@@ -1,3 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: kurrentdbclient
3
+ Version: 1.2
4
+ Summary: Python gRPC Client for KurrentDB
5
+ License: BSD-3-Clause
6
+ License-File: LICENSE
7
+ Author: John Bywater
8
+ Author-email: john.bywater@appropriatesoftware.net
9
+ Requires-Python: >=3.10
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: License :: OSI Approved :: BSD License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python
19
+ Provides-Extra: opentelemetry
20
+ Requires-Dist: googleapis-common-protos
21
+ Requires-Dist: grpcio-status
22
+ Requires-Dist: grpcio[protobuf] (>=1.75.1,<2.0)
23
+ Requires-Dist: opentelemetry-api (>=1.28.0,<2.0) ; extra == "opentelemetry"
24
+ Requires-Dist: opentelemetry-instrumentation (>=0.49b0) ; extra == "opentelemetry"
25
+ Requires-Dist: opentelemetry-semantic-conventions (>=0.49b0) ; extra == "opentelemetry"
26
+ Requires-Dist: typing_extensions
27
+ Project-URL: Homepage, https://github.com/pyeventsourcing/kurrentdbclient
28
+ Project-URL: Repository, https://github.com/pyeventsourcing/kurrentdbclient
29
+ Description-Content-Type: text/markdown
30
+
1
31
  <a href="https://kurrent.io">
2
32
  <picture>
3
33
  <source media="(prefers-color-scheme: dark)" srcset="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-White.png.png">
@@ -24,7 +54,7 @@ features are presented in an easy-to-use interface.
24
54
 
25
55
  These clients have been tested to work with KurrentDB version 25.1 and 25.0, EventStoreDB
26
56
  versions 24.10 and EventStoreDB 23.10, both with and without SSL/TLS, in both single-server and
27
- cluster modes, across Python versions 3.9, 3.10, 3.11, 3.12, 3.13, and 3.14.
57
+ cluster modes, across Python versions 3.10, 3.11, 3.12, 3.13, and 3.14.
28
58
 
29
59
  The test suite has 100% line and branch coverage. The code has typing annotations
30
60
  checked strictly with mypy. The code is formatted with black and isort, and checked
@@ -67,9 +97,11 @@ https://github.com/pyeventsourcing/eventsourcing-kurrentdb) package.
67
97
  * [Set stream metadata](#set-stream-metadata)
68
98
  * [Delete stream](#delete-stream)
69
99
  * [Tombstone stream](#tombstone-stream)
100
+ * [Read using secondary index](#read-index)
70
101
  * [Catch-up subscriptions](#catch-up-subscriptions)
71
102
  * [Subscribe to all events](#subscribe-to-all-events)
72
103
  * [Subscribe to stream events](#subscribe-to-stream-events)
104
+ * [Subscribe using secondary index](#subscribe-to-index)
73
105
  * [How to implement exactly-once event processing](#how-to-implement-exactly-once-event-processing)
74
106
  * [Persistent subscriptions](#persistent-subscriptions)
75
107
  * [Create subscription to all](#create-subscription-to-all)
@@ -1929,6 +1961,40 @@ commit_position = client.tombstone_stream(stream_name=stream_name1, current_vers
1929
1961
 
1930
1962
  After tombstoning a stream, it's not possible to append new events.
1931
1963
 
1964
+ ### Read using secondary index<a id="read-index"></a>
1965
+
1966
+ The method `read_index()` can be used to read from all events using a secondary index.
1967
+
1968
+ This method has one required argument, `index_name`.
1969
+
1970
+ The required `index_name` argument is a Python `str` that uniquely identifies
1971
+ an index from which to read, for example `"et-EventType"`. The KurrentDB convention
1972
+ for index names to start with `"idx-"` is supported by making it optional. That is
1973
+ to say, both `"et-EventType"` and `"$idx-et-EventType"` will return the same results.
1974
+
1975
+ This method has four optional arguments, `commit_position`, `limit`, `timeout`,
1976
+ and `credentials`.
1977
+
1978
+ The optional `commit_position` argument is a Python `int` that can be used to
1979
+ specify a commit position from which to start reading. The default value of
1980
+ `commit_position` is `None`. Please note, if a commit position is specified,
1981
+ it must be an actually existing commit position in the database. If this position
1982
+ corresponds to an event in the index, it will be returned. That is, reading is with
1983
+ this method is inclusive.
1984
+
1985
+ The optional `limit` argument is an integer which restricts the number of events that
1986
+ will be returned. The default value is `sys.maxint`.
1987
+
1988
+ The optional `timeout` argument is a Python `float` which sets a
1989
+ maximum duration, in seconds, for the completion of the gRPC operation.
1990
+
1991
+ The optional `credentials` argument can be used to
1992
+ override call credentials derived from the connection string URI.
1993
+
1994
+ The filtering of events is done on the KurrentDB server. The
1995
+ `limit` argument is applied on the server after filtering.
1996
+
1997
+ ...
1932
1998
 
1933
1999
  ## Catch-up subscriptions<a id="catch-up-subscriptions"></a>
1934
2000
 
@@ -2211,6 +2277,40 @@ subscription = client.subscribe_to_stream(
2211
2277
  )
2212
2278
  ```
2213
2279
 
2280
+ ### Subscribe using secondary index<a id="subscribe-to-index"></a>
2281
+
2282
+ The`subscribe_to_index()` method can be used to start a catch-up subscription
2283
+ that uses a secondary index from which events recorded in the database can
2284
+ be obtained in the order they were recorded. This method returns a "catch-up
2285
+ subscription" iterator.
2286
+
2287
+ This method has one required argument, `index_name`.
2288
+
2289
+ The required `index_name` argument is a Python `str` that uniquely identifies
2290
+ an index from which to read, for example `"et-EventType"`. The KurrentDB convention
2291
+ for index names to start with `"idx-"` is supported by making it optional. That is
2292
+ to say, both `"et-EventType"` and `"$idx-et-EventType"` will return the same results.
2293
+
2294
+ This method has three optional arguments, `commit_position`, `timeout`,
2295
+ and `credentials`.
2296
+
2297
+ The optional `commit_position` argument is a Python `int` that can be used to
2298
+ specify a commit position from which to start reading. The default value of
2299
+ `commit_position` is `None`. Please note, if a commit position is specified,
2300
+ it must be an actually existing commit position in the database. If this position
2301
+ corresponds to an event in the index, it will not be returned. That is, subscribing
2302
+ with this method is not inclusive. This is designed to help event-processing
2303
+ components checkpoint their progress with the commit positions of received events,
2304
+ and then resume from the last recorded commit position without receiving duplicate
2305
+ events.
2306
+
2307
+ The optional `timeout` argument is a Python `float` which sets a
2308
+ maximum duration, in seconds, for the completion of the gRPC operation.
2309
+
2310
+ The optional `credentials` argument can be used to
2311
+ override call credentials derived from the connection string URI.
2312
+
2313
+
2214
2314
  ### How to implement exactly-once event processing<a id="how-to-implement-exactly-once-event-processing"></a>
2215
2315
 
2216
2316
  The commit positions of recorded events that are received and processed by a
@@ -3838,4 +3938,5 @@ the project's virtual environment, with the following command.
3838
3938
 
3839
3939
  $ make update
3840
3940
 
3841
- Before pushing changes to the repo or a PR, please run `make lint test`.
3941
+ Before pushing changes to the repo or a PR, please run `make lint test`.
3942
+
@@ -1,34 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: kurrentdbclient
3
- Version: 1.1.2
4
- Summary: Python gRPC Client for KurrentDB
5
- License: BSD-3-Clause
6
- License-File: LICENSE
7
- Author: John Bywater
8
- Author-email: john.bywater@appropriatesoftware.net
9
- Requires-Python: >=3.9
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: License :: OSI Approved :: BSD License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Programming Language :: Python :: 3.13
17
- Classifier: Programming Language :: Python :: 3.14
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python
20
- Provides-Extra: opentelemetry
21
- Requires-Dist: googleapis-common-protos
22
- Requires-Dist: grpcio-status
23
- Requires-Dist: grpcio[protobuf] (>=1.75.1,<2.0)
24
- Requires-Dist: opentelemetry-api (>=1.28.0,<2.0) ; extra == "opentelemetry"
25
- Requires-Dist: opentelemetry-instrumentation (>=0.49b0) ; extra == "opentelemetry"
26
- Requires-Dist: opentelemetry-semantic-conventions (>=0.49b0) ; extra == "opentelemetry"
27
- Requires-Dist: typing_extensions
28
- Project-URL: Homepage, https://github.com/pyeventsourcing/kurrentdbclient
29
- Project-URL: Repository, https://github.com/pyeventsourcing/kurrentdbclient
30
- Description-Content-Type: text/markdown
31
-
32
1
  <a href="https://kurrent.io">
33
2
  <picture>
34
3
  <source media="(prefers-color-scheme: dark)" srcset="https://github.com/pyeventsourcing/kurrentdbclient/raw/1.0/KurrentLogo-White.png.png">
@@ -55,7 +24,7 @@ features are presented in an easy-to-use interface.
55
24
 
56
25
  These clients have been tested to work with KurrentDB version 25.1 and 25.0, EventStoreDB
57
26
  versions 24.10 and EventStoreDB 23.10, both with and without SSL/TLS, in both single-server and
58
- cluster modes, across Python versions 3.9, 3.10, 3.11, 3.12, 3.13, and 3.14.
27
+ cluster modes, across Python versions 3.10, 3.11, 3.12, 3.13, and 3.14.
59
28
 
60
29
  The test suite has 100% line and branch coverage. The code has typing annotations
61
30
  checked strictly with mypy. The code is formatted with black and isort, and checked
@@ -98,9 +67,11 @@ https://github.com/pyeventsourcing/eventsourcing-kurrentdb) package.
98
67
  * [Set stream metadata](#set-stream-metadata)
99
68
  * [Delete stream](#delete-stream)
100
69
  * [Tombstone stream](#tombstone-stream)
70
+ * [Read using secondary index](#read-index)
101
71
  * [Catch-up subscriptions](#catch-up-subscriptions)
102
72
  * [Subscribe to all events](#subscribe-to-all-events)
103
73
  * [Subscribe to stream events](#subscribe-to-stream-events)
74
+ * [Subscribe using secondary index](#subscribe-to-index)
104
75
  * [How to implement exactly-once event processing](#how-to-implement-exactly-once-event-processing)
105
76
  * [Persistent subscriptions](#persistent-subscriptions)
106
77
  * [Create subscription to all](#create-subscription-to-all)
@@ -1960,6 +1931,40 @@ commit_position = client.tombstone_stream(stream_name=stream_name1, current_vers
1960
1931
 
1961
1932
  After tombstoning a stream, it's not possible to append new events.
1962
1933
 
1934
+ ### Read using secondary index<a id="read-index"></a>
1935
+
1936
+ The method `read_index()` can be used to read from all events using a secondary index.
1937
+
1938
+ This method has one required argument, `index_name`.
1939
+
1940
+ The required `index_name` argument is a Python `str` that uniquely identifies
1941
+ an index from which to read, for example `"et-EventType"`. The KurrentDB convention
1942
+ for index names to start with `"idx-"` is supported by making it optional. That is
1943
+ to say, both `"et-EventType"` and `"$idx-et-EventType"` will return the same results.
1944
+
1945
+ This method has four optional arguments, `commit_position`, `limit`, `timeout`,
1946
+ and `credentials`.
1947
+
1948
+ The optional `commit_position` argument is a Python `int` that can be used to
1949
+ specify a commit position from which to start reading. The default value of
1950
+ `commit_position` is `None`. Please note, if a commit position is specified,
1951
+ it must be an actually existing commit position in the database. If this position
1952
+ corresponds to an event in the index, it will be returned. That is, reading is with
1953
+ this method is inclusive.
1954
+
1955
+ The optional `limit` argument is an integer which restricts the number of events that
1956
+ will be returned. The default value is `sys.maxint`.
1957
+
1958
+ The optional `timeout` argument is a Python `float` which sets a
1959
+ maximum duration, in seconds, for the completion of the gRPC operation.
1960
+
1961
+ The optional `credentials` argument can be used to
1962
+ override call credentials derived from the connection string URI.
1963
+
1964
+ The filtering of events is done on the KurrentDB server. The
1965
+ `limit` argument is applied on the server after filtering.
1966
+
1967
+ ...
1963
1968
 
1964
1969
  ## Catch-up subscriptions<a id="catch-up-subscriptions"></a>
1965
1970
 
@@ -2242,6 +2247,40 @@ subscription = client.subscribe_to_stream(
2242
2247
  )
2243
2248
  ```
2244
2249
 
2250
+ ### Subscribe using secondary index<a id="subscribe-to-index"></a>
2251
+
2252
+ The`subscribe_to_index()` method can be used to start a catch-up subscription
2253
+ that uses a secondary index from which events recorded in the database can
2254
+ be obtained in the order they were recorded. This method returns a "catch-up
2255
+ subscription" iterator.
2256
+
2257
+ This method has one required argument, `index_name`.
2258
+
2259
+ The required `index_name` argument is a Python `str` that uniquely identifies
2260
+ an index from which to read, for example `"et-EventType"`. The KurrentDB convention
2261
+ for index names to start with `"idx-"` is supported by making it optional. That is
2262
+ to say, both `"et-EventType"` and `"$idx-et-EventType"` will return the same results.
2263
+
2264
+ This method has three optional arguments, `commit_position`, `timeout`,
2265
+ and `credentials`.
2266
+
2267
+ The optional `commit_position` argument is a Python `int` that can be used to
2268
+ specify a commit position from which to start reading. The default value of
2269
+ `commit_position` is `None`. Please note, if a commit position is specified,
2270
+ it must be an actually existing commit position in the database. If this position
2271
+ corresponds to an event in the index, it will not be returned. That is, subscribing
2272
+ with this method is not inclusive. This is designed to help event-processing
2273
+ components checkpoint their progress with the commit positions of received events,
2274
+ and then resume from the last recorded commit position without receiving duplicate
2275
+ events.
2276
+
2277
+ The optional `timeout` argument is a Python `float` which sets a
2278
+ maximum duration, in seconds, for the completion of the gRPC operation.
2279
+
2280
+ The optional `credentials` argument can be used to
2281
+ override call credentials derived from the connection string URI.
2282
+
2283
+
2245
2284
  ### How to implement exactly-once event processing<a id="how-to-implement-exactly-once-event-processing"></a>
2246
2285
 
2247
2286
  The commit positions of recorded events that are received and processed by a
@@ -26,7 +26,7 @@ from kurrentdbclient.streams import (
26
26
  ReadResponse,
27
27
  )
28
28
 
29
- __version__ = "1.1.2"
29
+ __version__ = "1.2"
30
30
 
31
31
  __all__ = [
32
32
  "DEFAULT_EXCLUDE_FILTER",
@@ -4,18 +4,19 @@ import asyncio
4
4
  import json
5
5
  import sys
6
6
  from asyncio import Event, Lock
7
+ from collections.abc import Callable
7
8
  from functools import wraps
8
9
  from typing import (
9
10
  TYPE_CHECKING,
10
11
  Any,
11
- Callable,
12
+ Literal,
12
13
  TypeVar,
13
14
  cast,
14
15
  overload,
15
16
  )
16
17
 
17
18
  import grpc.aio
18
- from typing_extensions import Literal, Self
19
+ from typing_extensions import Self
19
20
 
20
21
  from kurrentdbclient.client import DEFAULT_EXCLUDE_FILTER, BaseKurrentDBClient
21
22
  from kurrentdbclient.common import (
@@ -37,12 +38,12 @@ from kurrentdbclient.common import (
37
38
  AbstractAsyncCatchupSubscription,
38
39
  AbstractAsyncPersistentSubscription,
39
40
  GrpcOptions,
40
- grpc_target,
41
41
  )
42
42
  from kurrentdbclient.connection import AsyncKurrentDBConnection
43
43
  from kurrentdbclient.connection_spec import (
44
44
  NODE_PREFERENCE_LEADER,
45
45
  URI_SCHEMES_NON_DISCOVER,
46
+ grpc_target,
46
47
  )
47
48
  from kurrentdbclient.events import NewEvent, NewEvents, RecordedEvent, StreamState
48
49
  from kurrentdbclient.exceptions import (
@@ -300,7 +301,7 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
300
301
  *,
301
302
  timeout: float | None = None,
302
303
  credentials: grpc.CallCredentials | None = None,
303
- ) -> int: # pragma: no v2cover
304
+ ) -> int: # pragma: <25.1 no cover
304
305
  """
305
306
  Appends new events to one or many streams.
306
307
  """
@@ -325,6 +326,7 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
325
326
  filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
326
327
  filter_include: Sequence[str] = (),
327
328
  filter_by_stream_name: bool = False,
329
+ filter_by_prefix: bool = False,
328
330
  limit: int = sys.maxsize,
329
331
  timeout: float | None = None,
330
332
  credentials: grpc.CallCredentials | None = None,
@@ -339,12 +341,36 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
339
341
  filter_exclude=filter_exclude,
340
342
  filter_include=filter_include,
341
343
  filter_by_stream_name=filter_by_stream_name,
344
+ filter_by_prefix=filter_by_prefix,
342
345
  limit=limit,
343
346
  timeout=timeout,
344
347
  metadata=self._call_metadata,
345
348
  credentials=credentials or self._call_credentials,
346
349
  )
347
350
 
351
+ async def read_index(
352
+ self,
353
+ index_name: str,
354
+ *,
355
+ commit_position: int | None = None,
356
+ limit: int = sys.maxsize,
357
+ timeout: float | None = None,
358
+ credentials: grpc.CallCredentials | None = None,
359
+ ) -> AsyncReadResponse: # pragma: <25.1 no cover
360
+
361
+ if not index_name.startswith("$idx-"):
362
+ index_name = f"$idx-{index_name}"
363
+
364
+ return await self.read_all(
365
+ commit_position=commit_position,
366
+ filter_include=(index_name,),
367
+ filter_by_stream_name=True,
368
+ filter_by_prefix=True,
369
+ limit=limit,
370
+ timeout=timeout,
371
+ credentials=credentials,
372
+ )
373
+
348
374
  @retrygrpc
349
375
  @autoreconnect
350
376
  async def get_commit_position(
@@ -492,6 +518,7 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
492
518
  filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
493
519
  filter_include: Sequence[str] = (),
494
520
  filter_by_stream_name: bool = False,
521
+ filter_by_prefix: bool = False,
495
522
  include_checkpoints: bool = False,
496
523
  window_size: int = DEFAULT_WINDOW_SIZE,
497
524
  checkpoint_interval_multiplier: int = DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
@@ -511,6 +538,7 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
511
538
  filter_exclude=filter_exclude,
512
539
  filter_include=filter_include,
513
540
  filter_by_stream_name=filter_by_stream_name,
541
+ filter_by_prefix=filter_by_prefix,
514
542
  subscribe=True,
515
543
  include_checkpoints=include_checkpoints,
516
544
  window_size=window_size,
@@ -522,6 +550,27 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
522
550
  credentials=credentials or self._call_credentials,
523
551
  )
524
552
 
553
+ async def subscribe_to_index(
554
+ self,
555
+ index_name: str,
556
+ *,
557
+ commit_position: int | None = None,
558
+ timeout: float | None = None,
559
+ credentials: grpc.CallCredentials | None = None,
560
+ ) -> AbstractAsyncCatchupSubscription: # pragma: <25.1 no cover
561
+
562
+ if not index_name.startswith("$idx-"):
563
+ index_name = f"$idx-{index_name}"
564
+
565
+ return await self.subscribe_to_all(
566
+ commit_position=commit_position,
567
+ filter_include=(index_name,),
568
+ filter_by_stream_name=True,
569
+ filter_by_prefix=True,
570
+ timeout=timeout,
571
+ credentials=credentials,
572
+ )
573
+
525
574
  #
526
575
  # @overload
527
576
  # async def subscribe_to_stream(
@@ -4,20 +4,21 @@ import json
4
4
  import random
5
5
  import sys
6
6
  from abc import ABC, abstractmethod
7
+ from collections.abc import Callable
7
8
  from functools import wraps
8
9
  from threading import Event, Lock
9
10
  from time import sleep
10
11
  from typing import (
11
12
  TYPE_CHECKING,
12
13
  Any,
13
- Callable,
14
+ Literal,
14
15
  TypeVar,
15
16
  cast,
16
17
  overload,
17
18
  )
18
19
 
19
20
  import grpc
20
- from typing_extensions import Literal, Self
21
+ from typing_extensions import Self
21
22
 
22
23
  from kurrentdbclient.common import (
23
24
  DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
@@ -40,7 +41,6 @@ from kurrentdbclient.common import (
40
41
  AbstractReadResponse,
41
42
  BasicAuthCallCredentials,
42
43
  GrpcOptions,
43
- grpc_target,
44
44
  )
45
45
  from kurrentdbclient.connection import KurrentDBConnection
46
46
  from kurrentdbclient.connection_spec import (
@@ -50,6 +50,7 @@ from kurrentdbclient.connection_spec import (
50
50
  NODE_PREFERENCE_REPLICA,
51
51
  URI_SCHEMES_NON_DISCOVER,
52
52
  ConnectionSpec,
53
+ grpc_target,
53
54
  )
54
55
  from kurrentdbclient.events import NewEvent, NewEvents, RecordedEvent, StreamState
55
56
  from kurrentdbclient.exceptions import (
@@ -70,10 +71,6 @@ from kurrentdbclient.gossip import (
70
71
  GossipService,
71
72
  )
72
73
 
73
- if TYPE_CHECKING:
74
- from kurrentdbclient.streams import StreamsService
75
- from kurrentdbclient.v2streams import V2StreamsService
76
-
77
74
  if TYPE_CHECKING:
78
75
  from collections.abc import Iterable, Sequence
79
76
 
@@ -87,6 +84,8 @@ if TYPE_CHECKING:
87
84
  ProjectionState,
88
85
  ProjectionStatistics,
89
86
  )
87
+ from kurrentdbclient.streams import StreamsService
88
+ from kurrentdbclient.v2streams import V2StreamsService
90
89
 
91
90
  # Matches the 'type' of "system" events.
92
91
  KDB_SYSTEM_EVENTS_REGEX = r"\$.+"
@@ -310,7 +309,7 @@ class KurrentDBClient(BaseKurrentDBClient):
310
309
  return self._connection.streams
311
310
 
312
311
  @property
313
- def v2streams(self) -> V2StreamsService: # pragma: no v2cover
312
+ def v2streams(self) -> V2StreamsService: # pragma: <25.1 no cover
314
313
  return self._connection.v2streams
315
314
 
316
315
  @property
@@ -565,7 +564,7 @@ class KurrentDBClient(BaseKurrentDBClient):
565
564
  *,
566
565
  timeout: float | None = None,
567
566
  credentials: grpc.CallCredentials | None = None,
568
- ) -> int: # pragma: no v2cover
567
+ ) -> int: # pragma: <25.1 no cover
569
568
  """
570
569
  Appends new events to one or many streams.
571
570
  """
@@ -679,6 +678,7 @@ class KurrentDBClient(BaseKurrentDBClient):
679
678
  filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
680
679
  filter_include: Sequence[str] = (),
681
680
  filter_by_stream_name: bool = False,
681
+ filter_by_prefix: bool = False,
682
682
  limit: int = sys.maxsize,
683
683
  timeout: float | None = None,
684
684
  credentials: grpc.CallCredentials | None = None,
@@ -693,12 +693,36 @@ class KurrentDBClient(BaseKurrentDBClient):
693
693
  filter_exclude=filter_exclude,
694
694
  filter_include=filter_include,
695
695
  filter_by_stream_name=filter_by_stream_name,
696
+ filter_by_prefix=filter_by_prefix,
696
697
  limit=limit,
697
698
  timeout=timeout,
698
699
  metadata=self._call_metadata,
699
700
  credentials=credentials or self._call_credentials,
700
701
  )
701
702
 
703
+ def read_index(
704
+ self,
705
+ index_name: str,
706
+ *,
707
+ commit_position: int | None = None,
708
+ limit: int = sys.maxsize,
709
+ timeout: float | None = None,
710
+ credentials: grpc.CallCredentials | None = None,
711
+ ) -> AbstractReadResponse: # pragma: <25.1 no cover
712
+
713
+ if not index_name.startswith("$idx-"):
714
+ index_name = f"$idx-{index_name}"
715
+
716
+ return self.read_all(
717
+ commit_position=commit_position,
718
+ filter_include=(index_name,),
719
+ filter_by_stream_name=True,
720
+ filter_by_prefix=True,
721
+ limit=limit,
722
+ timeout=timeout,
723
+ credentials=credentials,
724
+ )
725
+
702
726
  @retrygrpc
703
727
  @autoreconnect
704
728
  def get_current_version(
@@ -827,6 +851,7 @@ class KurrentDBClient(BaseKurrentDBClient):
827
851
  filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
828
852
  filter_include: Sequence[str] = (),
829
853
  filter_by_stream_name: bool = False,
854
+ filter_by_prefix: bool = False,
830
855
  include_checkpoints: bool = False,
831
856
  window_size: int = DEFAULT_WINDOW_SIZE,
832
857
  checkpoint_interval_multiplier: int = DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
@@ -846,6 +871,7 @@ class KurrentDBClient(BaseKurrentDBClient):
846
871
  filter_exclude=filter_exclude,
847
872
  filter_include=filter_include,
848
873
  filter_by_stream_name=filter_by_stream_name,
874
+ filter_by_prefix=filter_by_prefix,
849
875
  subscribe=True,
850
876
  include_checkpoints=include_checkpoints,
851
877
  window_size=window_size,
@@ -857,6 +883,27 @@ class KurrentDBClient(BaseKurrentDBClient):
857
883
  credentials=credentials or self._call_credentials,
858
884
  )
859
885
 
886
+ def subscribe_to_index(
887
+ self,
888
+ index_name: str,
889
+ *,
890
+ commit_position: int | None = None,
891
+ timeout: float | None = None,
892
+ credentials: grpc.CallCredentials | None = None,
893
+ ) -> AbstractCatchupSubscription: # pragma: <25.1 no cover
894
+
895
+ if not index_name.startswith("$idx-"):
896
+ index_name = f"$idx-{index_name}"
897
+
898
+ return self.subscribe_to_all(
899
+ commit_position=commit_position,
900
+ filter_include=(index_name,),
901
+ filter_by_stream_name=True,
902
+ filter_by_prefix=True,
903
+ timeout=timeout,
904
+ credentials=credentials,
905
+ )
906
+
860
907
  # @overload
861
908
  # def subscribe_to_stream(
862
909
  # self,
@@ -1079,6 +1126,62 @@ class KurrentDBClient(BaseKurrentDBClient):
1079
1126
  credentials=credentials or self._call_credentials,
1080
1127
  )
1081
1128
 
1129
+ # @retrygrpc
1130
+ # @autoreconnect
1131
+ # def create_subscription_to_index(
1132
+ # self,
1133
+ # group_name: str,
1134
+ # *,
1135
+ # index_name: str,
1136
+ # from_end: bool = False,
1137
+ # commit_position: int | None = None,
1138
+ # window_size: int = DEFAULT_WINDOW_SIZE,
1139
+ # checkpoint_interval_multiplier: int = DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
1140
+ # consumer_strategy: ConsumerStrategy = "DispatchToSingle",
1141
+ # message_timeout: float = DEFAULT_PERSISTENT_SUB_MESSAGE_TIMEOUT,
1142
+ # max_retry_count: int = DEFAULT_PERSISTENT_SUB_MAX_RETRY_COUNT,
1143
+ # min_checkpoint_count: int = DEFAULT_PERSISTENT_SUB_MIN_CHECKPOINT_COUNT,
1144
+ # max_checkpoint_count: int = DEFAULT_PERSISTENT_SUB_MAX_CHECKPOINT_COUNT,
1145
+ # checkpoint_after: float = DEFAULT_PERSISTENT_SUB_CHECKPOINT_AFTER,
1146
+ # max_subscriber_count: int = DEFAULT_PERSISTENT_SUB_MAX_SUBSCRIBER_COUNT,
1147
+ # live_buffer_size: int = DEFAULT_PERSISTENT_SUB_LIVE_BUFFER_SIZE,
1148
+ # read_batch_size: int = DEFAULT_PERSISTENT_SUB_READ_BATCH_SIZE,
1149
+ # history_buffer_size: int = DEFAULT_PERSISTENT_SUB_HISTORY_BUFFER_SIZE,
1150
+ # extra_statistics: bool = False,
1151
+ # timeout: float | None = None,
1152
+ # credentials: grpc.CallCredentials | None = None,
1153
+ # ) -> None:
1154
+ # if not index_name.startswith("$idx-"):
1155
+ # index_name = f"$idx-{index_name}"
1156
+ #
1157
+ # timeout = timeout if timeout is not None else self._default_deadline
1158
+ #
1159
+ # return self.persistent_subscriptions.create(
1160
+ # group_name=group_name,
1161
+ # from_end=from_end,
1162
+ # commit_position=commit_position,
1163
+ # resolve_links=False,
1164
+ # consumer_strategy=consumer_strategy,
1165
+ # filter_include=(index_name,),
1166
+ # filter_by_stream_name=True,
1167
+ # filter_by_prefix=True,
1168
+ # window_size=window_size,
1169
+ # checkpoint_interval_multiplier=checkpoint_interval_multiplier,
1170
+ # message_timeout=message_timeout,
1171
+ # max_retry_count=max_retry_count,
1172
+ # min_checkpoint_count=min_checkpoint_count,
1173
+ # max_checkpoint_count=max_checkpoint_count,
1174
+ # checkpoint_after=checkpoint_after,
1175
+ # max_subscriber_count=max_subscriber_count,
1176
+ # live_buffer_size=live_buffer_size,
1177
+ # read_batch_size=read_batch_size,
1178
+ # history_buffer_size=history_buffer_size,
1179
+ # extra_statistics=extra_statistics,
1180
+ # timeout=timeout,
1181
+ # metadata=self._call_metadata,
1182
+ # credentials=credentials or self._call_credentials,
1183
+ # )
1184
+
1082
1185
  @overload
1083
1186
  def create_subscription_to_stream(
1084
1187
  self,