kurrentdbclient 1.2.3__tar.gz → 1.3.0__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.
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/PKG-INFO +3 -3
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/README.md +1 -1
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/__init__.py +5 -1
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/asyncio_client.py +70 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/client.py +71 -3
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/common.py +38 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/events.py +26 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/exceptions.py +43 -4
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/projections.py +27 -6
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/google/rpc/code_pb2.pyi +12 -12
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/google/rpc/code_pb2_grpc.py +2 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/kurrent/rpc/errors_pb2.pyi +74 -61
- {kurrentdbclient-1.2.3/kurrentdbclient/protos/v2/streams → kurrentdbclient-1.3.0/kurrentdbclient/protos/kurrent/rpc}/errors_pb2_grpc.py +2 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/kurrent/rpc/rpc_pb2.pyi +33 -23
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/kurrent/rpc/rpc_pb2_grpc.py +2 -2
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/cluster_pb2.pyi +855 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/cluster_pb2_grpc.py +2 -2
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/gossip_pb2.pyi +137 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/gossip_pb2_grpc.py +2 -2
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/persistent_pb2.pyi +1333 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/persistent_pb2_grpc.py +2 -2
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/projections_pb2.py +101 -0
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/projections_pb2.pyi +688 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/projections_pb2_grpc.py +2 -2
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/shared_pb2.pyi +282 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/shared_pb2_grpc.py +2 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/status_pb2.pyi +32 -23
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/status_pb2_grpc.py +2 -2
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v1/streams_pb2.pyi +1307 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/streams_pb2_grpc.py +2 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v2/streams/errors_pb2.py +11 -3
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v2/streams/errors_pb2.pyi +586 -0
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v2/streams/errors_pb2_grpc.py +24 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v2/streams/streams_pb2.py +20 -10
- kurrentdbclient-1.3.0/kurrentdbclient/protos/v2/streams/streams_pb2.pyi +498 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v2/streams/streams_pb2_grpc.py +65 -2
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/streams.py +47 -8
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/v2streams.py +157 -50
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/pyproject.toml +2 -2
- kurrentdbclient-1.2.3/kurrentdbclient/.DS_Store +0 -0
- kurrentdbclient-1.2.3/kurrentdbclient/protos/kurrent/rpc/errors_pb2_grpc.py +0 -24
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/cluster_pb2.pyi +0 -765
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/gossip_pb2.pyi +0 -126
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/persistent_pb2.pyi +0 -1135
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/projections_pb2.py +0 -99
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/projections_pb2.pyi +0 -558
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/shared_pb2.pyi +0 -218
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v1/streams_pb2.pyi +0 -1123
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v2/streams/errors_pb2.pyi +0 -415
- kurrentdbclient-1.2.3/kurrentdbclient/protos/v2/streams/streams_pb2.pyi +0 -296
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/LICENSE +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/connection.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/connection_spec.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/gossip.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/__init__.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/__init__.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/attributes.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/grpc.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/package.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/spanners.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/utils.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/instrumentation/opentelemetry/version.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/persistent.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/google/rpc/code_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/kurrent/rpc/errors_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/kurrent/rpc/rpc_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/cluster_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/gossip_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/persistent_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/shared_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/status_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/v1/streams_pb2.py +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/py.typed +0 -0
- {kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/unpack_error_status.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kurrentdbclient
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Python gRPC Client for KurrentDB
|
|
5
5
|
License: BSD-3-Clause
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python
|
|
|
19
19
|
Provides-Extra: opentelemetry
|
|
20
20
|
Requires-Dist: googleapis-common-protos
|
|
21
21
|
Requires-Dist: grpcio-status
|
|
22
|
-
Requires-Dist: grpcio[protobuf] (>=1.
|
|
22
|
+
Requires-Dist: grpcio[protobuf] (>=1.80.0,<2.0)
|
|
23
23
|
Requires-Dist: opentelemetry-api (>=1.28.0,<2.0) ; extra == "opentelemetry"
|
|
24
24
|
Requires-Dist: opentelemetry-instrumentation (>=0.62b1) ; extra == "opentelemetry"
|
|
25
25
|
Requires-Dist: opentelemetry-semantic-conventions (>=0.62b1) ; extra == "opentelemetry"
|
|
@@ -83,7 +83,7 @@ https://github.com/pyeventsourcing/eventsourcing-kurrentdb) package.
|
|
|
83
83
|
* [Query string](#query-string)
|
|
84
84
|
* [Examples](#examples)
|
|
85
85
|
* [Event objects](#event-objects)
|
|
86
|
-
* [New events](#
|
|
86
|
+
* [New events](#the-newevent-class)
|
|
87
87
|
* [Recorded events](#recorded-events)
|
|
88
88
|
* [Streams](#streams)
|
|
89
89
|
* [Append events](#append-events)
|
|
@@ -53,7 +53,7 @@ https://github.com/pyeventsourcing/eventsourcing-kurrentdb) package.
|
|
|
53
53
|
* [Query string](#query-string)
|
|
54
54
|
* [Examples](#examples)
|
|
55
55
|
* [Event objects](#event-objects)
|
|
56
|
-
* [New events](#
|
|
56
|
+
* [New events](#the-newevent-class)
|
|
57
57
|
* [Recorded events](#recorded-events)
|
|
58
58
|
* [Streams](#streams)
|
|
59
59
|
* [Append events](#append-events)
|
|
@@ -12,8 +12,10 @@ from kurrentdbclient.events import (
|
|
|
12
12
|
FellBehind,
|
|
13
13
|
NewEvent,
|
|
14
14
|
NewEvents,
|
|
15
|
+
NewRecord,
|
|
15
16
|
RecordedEvent,
|
|
16
17
|
StreamState,
|
|
18
|
+
StreamStateCheck,
|
|
17
19
|
)
|
|
18
20
|
from kurrentdbclient.persistent import (
|
|
19
21
|
AsyncPersistentSubscription,
|
|
@@ -26,7 +28,7 @@ from kurrentdbclient.streams import (
|
|
|
26
28
|
ReadResponse,
|
|
27
29
|
)
|
|
28
30
|
|
|
29
|
-
__version__ = "1.
|
|
31
|
+
__version__ = "1.3.0"
|
|
30
32
|
|
|
31
33
|
__all__ = [
|
|
32
34
|
"DEFAULT_EXCLUDE_FILTER",
|
|
@@ -44,8 +46,10 @@ __all__ = [
|
|
|
44
46
|
"KurrentDBClient",
|
|
45
47
|
"NewEvent",
|
|
46
48
|
"NewEvents",
|
|
49
|
+
"NewRecord",
|
|
47
50
|
"RecordedEvent",
|
|
48
51
|
"ReadResponse",
|
|
49
52
|
"StreamState",
|
|
53
|
+
"StreamStateCheck",
|
|
50
54
|
"PersistentSubscription",
|
|
51
55
|
]
|
|
@@ -45,7 +45,14 @@ from kurrentdbclient.connection_spec import (
|
|
|
45
45
|
URI_SCHEMES_NON_DISCOVER,
|
|
46
46
|
grpc_target,
|
|
47
47
|
)
|
|
48
|
-
from kurrentdbclient.events import
|
|
48
|
+
from kurrentdbclient.events import (
|
|
49
|
+
NewEvent,
|
|
50
|
+
NewEvents,
|
|
51
|
+
NewRecord,
|
|
52
|
+
RecordedEvent,
|
|
53
|
+
StreamState,
|
|
54
|
+
StreamStateCheck,
|
|
55
|
+
)
|
|
49
56
|
from kurrentdbclient.exceptions import (
|
|
50
57
|
DeadlineExceededError,
|
|
51
58
|
DiscoveryFailedError,
|
|
@@ -62,6 +69,7 @@ if TYPE_CHECKING:
|
|
|
62
69
|
from kurrentdbclient.persistent import ConsumerStrategy, SubscriptionInfo
|
|
63
70
|
from kurrentdbclient.projections import ProjectionState, ProjectionStatistics
|
|
64
71
|
from kurrentdbclient.streams import AsyncReadResponse
|
|
72
|
+
from kurrentdbclient.v2streams import AppendRecordsResult
|
|
65
73
|
|
|
66
74
|
_TCallable = TypeVar("_TCallable", bound=Callable[..., Any])
|
|
67
75
|
|
|
@@ -331,6 +339,33 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
|
|
|
331
339
|
credentials=credentials or self._call_credentials,
|
|
332
340
|
)
|
|
333
341
|
|
|
342
|
+
@retrygrpc
|
|
343
|
+
@autoreconnect
|
|
344
|
+
async def append_records(
|
|
345
|
+
self,
|
|
346
|
+
/,
|
|
347
|
+
records: NewRecord | Iterable[NewRecord],
|
|
348
|
+
checks: StreamStateCheck | Iterable[StreamStateCheck] | None = None,
|
|
349
|
+
*,
|
|
350
|
+
timeout: float | None = None,
|
|
351
|
+
credentials: grpc.CallCredentials | None = None,
|
|
352
|
+
) -> AppendRecordsResult: # pragma: <26.1 no cover
|
|
353
|
+
"""
|
|
354
|
+
Appends new events to one or many streams.
|
|
355
|
+
"""
|
|
356
|
+
timeout = timeout if timeout is not None else self._default_deadline
|
|
357
|
+
if isinstance(records, NewRecord):
|
|
358
|
+
records = [records]
|
|
359
|
+
if isinstance(checks, StreamStateCheck):
|
|
360
|
+
checks = [checks]
|
|
361
|
+
return await self.connection.v2streams.append_records(
|
|
362
|
+
records=records,
|
|
363
|
+
checks=checks,
|
|
364
|
+
timeout=timeout,
|
|
365
|
+
metadata=self._call_metadata,
|
|
366
|
+
credentials=credentials or self._call_credentials,
|
|
367
|
+
)
|
|
368
|
+
|
|
334
369
|
@retrygrpc
|
|
335
370
|
@autoreconnect
|
|
336
371
|
async def read_all(
|
|
@@ -1485,6 +1520,37 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
|
|
|
1485
1520
|
credentials=credentials or self._call_credentials,
|
|
1486
1521
|
)
|
|
1487
1522
|
|
|
1523
|
+
@overload
|
|
1524
|
+
async def create_projection(
|
|
1525
|
+
self,
|
|
1526
|
+
*,
|
|
1527
|
+
name: str,
|
|
1528
|
+
query: str,
|
|
1529
|
+
engine_version: Literal["v1"] = "v1",
|
|
1530
|
+
emit_enabled: bool = False,
|
|
1531
|
+
track_emitted_streams: bool = False,
|
|
1532
|
+
timeout: float | None = None,
|
|
1533
|
+
credentials: grpc.CallCredentials | None = None,
|
|
1534
|
+
) -> None:
|
|
1535
|
+
"""
|
|
1536
|
+
Creates a projection using the v1 engine.
|
|
1537
|
+
"""
|
|
1538
|
+
|
|
1539
|
+
@overload
|
|
1540
|
+
async def create_projection(
|
|
1541
|
+
self,
|
|
1542
|
+
*,
|
|
1543
|
+
name: str,
|
|
1544
|
+
query: str,
|
|
1545
|
+
engine_version: Literal["v2"],
|
|
1546
|
+
emit_enabled: bool = False,
|
|
1547
|
+
timeout: float | None = None,
|
|
1548
|
+
credentials: grpc.CallCredentials | None = None,
|
|
1549
|
+
) -> None:
|
|
1550
|
+
"""
|
|
1551
|
+
Creates a projection using the v2 engine.
|
|
1552
|
+
"""
|
|
1553
|
+
|
|
1488
1554
|
@retrygrpc
|
|
1489
1555
|
@autoreconnect
|
|
1490
1556
|
async def create_projection(
|
|
@@ -1492,6 +1558,7 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
|
|
|
1492
1558
|
*,
|
|
1493
1559
|
name: str,
|
|
1494
1560
|
query: str,
|
|
1561
|
+
engine_version: Literal["v1", "v2"] = "v1",
|
|
1495
1562
|
emit_enabled: bool = False,
|
|
1496
1563
|
track_emitted_streams: bool = False,
|
|
1497
1564
|
timeout: float | None = None,
|
|
@@ -1503,8 +1570,9 @@ class AsyncKurrentDBClient(BaseKurrentDBClient):
|
|
|
1503
1570
|
timeout = timeout if timeout is not None else self._default_deadline
|
|
1504
1571
|
|
|
1505
1572
|
await self.connection.projections.create(
|
|
1506
|
-
query=query,
|
|
1507
1573
|
name=name,
|
|
1574
|
+
query=query,
|
|
1575
|
+
engine_version=engine_version,
|
|
1508
1576
|
emit_enabled=emit_enabled,
|
|
1509
1577
|
track_emitted_streams=track_emitted_streams,
|
|
1510
1578
|
timeout=timeout,
|
|
@@ -52,7 +52,15 @@ from kurrentdbclient.connection_spec import (
|
|
|
52
52
|
ConnectionSpec,
|
|
53
53
|
grpc_target,
|
|
54
54
|
)
|
|
55
|
-
from kurrentdbclient.events import
|
|
55
|
+
from kurrentdbclient.events import (
|
|
56
|
+
ConsistencyCheck,
|
|
57
|
+
NewEvent,
|
|
58
|
+
NewEvents,
|
|
59
|
+
NewRecord,
|
|
60
|
+
RecordedEvent,
|
|
61
|
+
StreamState,
|
|
62
|
+
StreamStateCheck,
|
|
63
|
+
)
|
|
56
64
|
from kurrentdbclient.exceptions import (
|
|
57
65
|
DiscoveryFailedError,
|
|
58
66
|
FollowerNotFoundError,
|
|
@@ -85,7 +93,7 @@ if TYPE_CHECKING:
|
|
|
85
93
|
ProjectionStatistics,
|
|
86
94
|
)
|
|
87
95
|
from kurrentdbclient.streams import StreamsService
|
|
88
|
-
from kurrentdbclient.v2streams import V2StreamsService
|
|
96
|
+
from kurrentdbclient.v2streams import AppendRecordsResult, V2StreamsService
|
|
89
97
|
|
|
90
98
|
# Matches the 'type' of "system" events.
|
|
91
99
|
KDB_SYSTEM_EVENTS_REGEX = r"\$.+"
|
|
@@ -578,6 +586,33 @@ class KurrentDBClient(BaseKurrentDBClient):
|
|
|
578
586
|
credentials=credentials or self._call_credentials,
|
|
579
587
|
)
|
|
580
588
|
|
|
589
|
+
@retrygrpc
|
|
590
|
+
@autoreconnect
|
|
591
|
+
def append_records(
|
|
592
|
+
self,
|
|
593
|
+
/,
|
|
594
|
+
records: NewRecord | Iterable[NewRecord],
|
|
595
|
+
checks: ConsistencyCheck | Iterable[ConsistencyCheck] | None = None,
|
|
596
|
+
*,
|
|
597
|
+
timeout: float | None = None,
|
|
598
|
+
credentials: grpc.CallCredentials | None = None,
|
|
599
|
+
) -> AppendRecordsResult: # pragma: <26.1 no cover
|
|
600
|
+
"""
|
|
601
|
+
Appends new events to one or many streams.
|
|
602
|
+
"""
|
|
603
|
+
timeout = timeout if timeout is not None else self._default_deadline
|
|
604
|
+
if isinstance(records, NewRecord):
|
|
605
|
+
records = [records]
|
|
606
|
+
if isinstance(checks, StreamStateCheck):
|
|
607
|
+
checks = [checks]
|
|
608
|
+
return self.v2streams.append_records(
|
|
609
|
+
records=records,
|
|
610
|
+
checks=checks,
|
|
611
|
+
timeout=timeout,
|
|
612
|
+
metadata=self._call_metadata,
|
|
613
|
+
credentials=credentials or self._call_credentials,
|
|
614
|
+
)
|
|
615
|
+
|
|
581
616
|
@retrygrpc
|
|
582
617
|
@autoreconnect
|
|
583
618
|
def delete_stream(
|
|
@@ -1803,6 +1838,37 @@ class KurrentDBClient(BaseKurrentDBClient):
|
|
|
1803
1838
|
credentials=credentials or self._call_credentials,
|
|
1804
1839
|
)
|
|
1805
1840
|
|
|
1841
|
+
@overload
|
|
1842
|
+
def create_projection(
|
|
1843
|
+
self,
|
|
1844
|
+
*,
|
|
1845
|
+
name: str,
|
|
1846
|
+
query: str,
|
|
1847
|
+
engine_version: Literal["v1"] = "v1",
|
|
1848
|
+
emit_enabled: bool = False,
|
|
1849
|
+
track_emitted_streams: bool = False,
|
|
1850
|
+
timeout: float | None = None,
|
|
1851
|
+
credentials: grpc.CallCredentials | None = None,
|
|
1852
|
+
) -> None:
|
|
1853
|
+
"""
|
|
1854
|
+
Creates a projection using the v1 engine.
|
|
1855
|
+
"""
|
|
1856
|
+
|
|
1857
|
+
@overload
|
|
1858
|
+
def create_projection(
|
|
1859
|
+
self,
|
|
1860
|
+
*,
|
|
1861
|
+
name: str,
|
|
1862
|
+
query: str,
|
|
1863
|
+
engine_version: Literal["v2"],
|
|
1864
|
+
emit_enabled: bool = False,
|
|
1865
|
+
timeout: float | None = None,
|
|
1866
|
+
credentials: grpc.CallCredentials | None = None,
|
|
1867
|
+
) -> None:
|
|
1868
|
+
"""
|
|
1869
|
+
Creates a projection using the v2 engine.
|
|
1870
|
+
"""
|
|
1871
|
+
|
|
1806
1872
|
@retrygrpc
|
|
1807
1873
|
@autoreconnect
|
|
1808
1874
|
def create_projection(
|
|
@@ -1810,6 +1876,7 @@ class KurrentDBClient(BaseKurrentDBClient):
|
|
|
1810
1876
|
*,
|
|
1811
1877
|
name: str,
|
|
1812
1878
|
query: str,
|
|
1879
|
+
engine_version: Literal["v1", "v2"] = "v1",
|
|
1813
1880
|
emit_enabled: bool = False,
|
|
1814
1881
|
track_emitted_streams: bool = False,
|
|
1815
1882
|
timeout: float | None = None,
|
|
@@ -1821,8 +1888,9 @@ class KurrentDBClient(BaseKurrentDBClient):
|
|
|
1821
1888
|
timeout = timeout if timeout is not None else self._default_deadline
|
|
1822
1889
|
|
|
1823
1890
|
self.projections.create(
|
|
1824
|
-
query=query,
|
|
1825
1891
|
name=name,
|
|
1892
|
+
query=query,
|
|
1893
|
+
engine_version=engine_version,
|
|
1826
1894
|
emit_enabled=emit_enabled,
|
|
1827
1895
|
track_emitted_streams=track_emitted_streams,
|
|
1828
1896
|
timeout=timeout,
|
|
@@ -7,7 +7,7 @@ import os
|
|
|
7
7
|
import threading
|
|
8
8
|
from abc import ABC, abstractmethod
|
|
9
9
|
from base64 import b64encode
|
|
10
|
-
from collections.abc import AsyncIterator, Iterator, Sequence
|
|
10
|
+
from collections.abc import AsyncIterator, Iterable, Iterator, Sequence
|
|
11
11
|
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
12
12
|
from typing import (
|
|
13
13
|
TYPE_CHECKING,
|
|
@@ -31,6 +31,8 @@ from kurrentdbclient.exceptions import (
|
|
|
31
31
|
AbortedByServerError,
|
|
32
32
|
AlreadyExistsError,
|
|
33
33
|
CancelledByClientError,
|
|
34
|
+
ConsistencyCheckFailure,
|
|
35
|
+
ConsistencyChecksFailedError,
|
|
34
36
|
ConsumerTooSlowError,
|
|
35
37
|
ExceptionThrownByHandlerError,
|
|
36
38
|
FailedPreconditionError,
|
|
@@ -47,6 +49,7 @@ from kurrentdbclient.exceptions import (
|
|
|
47
49
|
RecordMaxSizeExceededError,
|
|
48
50
|
ServiceUnavailableError,
|
|
49
51
|
SSLError,
|
|
52
|
+
StreamStateCheckFailure,
|
|
50
53
|
StreamTombstonedError,
|
|
51
54
|
TransactionMaxSizeExceededError,
|
|
52
55
|
UnauthenticatedError,
|
|
@@ -239,7 +242,7 @@ def handle_rpc_error(e: grpc.RpcError) -> KurrentDBClientError: # noqa: PLR0911
|
|
|
239
242
|
"actual", "current"
|
|
240
243
|
),
|
|
241
244
|
stream_name=unpacked_detail.stream,
|
|
242
|
-
|
|
245
|
+
actual_version=unpacked_detail.actual_revision,
|
|
243
246
|
expected_version=unpacked_detail.expected_revision,
|
|
244
247
|
)
|
|
245
248
|
if isinstance(
|
|
@@ -249,6 +252,16 @@ def handle_rpc_error(e: grpc.RpcError) -> KurrentDBClientError: # noqa: PLR0911
|
|
|
249
252
|
return StreamTombstonedError(
|
|
250
253
|
rich_status.message, stream_name=unpacked_detail.stream
|
|
251
254
|
)
|
|
255
|
+
if isinstance(
|
|
256
|
+
unpacked_detail,
|
|
257
|
+
v2streams_errors_pb2.AppendConsistencyViolationErrorDetails,
|
|
258
|
+
):
|
|
259
|
+
return ConsistencyChecksFailedError(
|
|
260
|
+
rich_status.message,
|
|
261
|
+
failures=_convert_append_consistency_violations(
|
|
262
|
+
unpacked_detail.violations
|
|
263
|
+
),
|
|
264
|
+
)
|
|
252
265
|
if status_msg.code == grpc.StatusCode.INVALID_ARGUMENT: # noqa: SIM102
|
|
253
266
|
if isinstance(
|
|
254
267
|
unpacked_detail,
|
|
@@ -381,6 +394,29 @@ def handle_rpc_error(e: grpc.RpcError) -> KurrentDBClientError: # noqa: PLR0911
|
|
|
381
394
|
return GrpcError(str(e))
|
|
382
395
|
|
|
383
396
|
|
|
397
|
+
def _convert_append_consistency_violations(
|
|
398
|
+
violations: Iterable[v2streams_errors_pb2.ConsistencyViolation],
|
|
399
|
+
) -> tuple[ConsistencyCheckFailure, ...]:
|
|
400
|
+
failures = []
|
|
401
|
+
for violation in violations:
|
|
402
|
+
which_type = violation.WhichOneof("type")
|
|
403
|
+
if which_type == "stream_state":
|
|
404
|
+
stream_state_violation = violation.stream_state
|
|
405
|
+
failures.append(
|
|
406
|
+
ConsistencyCheckFailure(
|
|
407
|
+
check_index=violation.check_index,
|
|
408
|
+
stream_state_failure=StreamStateCheckFailure(
|
|
409
|
+
stream_name=stream_state_violation.stream,
|
|
410
|
+
expected_state=stream_state_violation.expected_state,
|
|
411
|
+
actual_state=stream_state_violation.actual_state,
|
|
412
|
+
),
|
|
413
|
+
)
|
|
414
|
+
)
|
|
415
|
+
else: # pragma: no cover
|
|
416
|
+
pass
|
|
417
|
+
return tuple(failures)
|
|
418
|
+
|
|
419
|
+
|
|
384
420
|
class KurrentDBService(Generic[TGrpcStreamers]):
|
|
385
421
|
def __init__(
|
|
386
422
|
self,
|
|
@@ -47,6 +47,32 @@ class NewEvents:
|
|
|
47
47
|
current_version: int | StreamState
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class NewRecord:
|
|
52
|
+
"""
|
|
53
|
+
Encapsulates event data to be recorded in KurrentDB.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
stream_name: str
|
|
57
|
+
type: str
|
|
58
|
+
data: bytes
|
|
59
|
+
metadata: bytes = b""
|
|
60
|
+
content_type: ContentType = "application/json"
|
|
61
|
+
id: UUID = field(default_factory=uuid4)
|
|
62
|
+
|
|
63
|
+
def __eq__(self, other: object) -> bool: # pragma: no cover
|
|
64
|
+
return isinstance(other, NewRecord) and self.id == other.id
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass(frozen=True)
|
|
68
|
+
class StreamStateCheck:
|
|
69
|
+
stream_name: str
|
|
70
|
+
expected_state: StreamState | int
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
ConsistencyCheck = StreamStateCheck # ... | QueryPredicateCheck
|
|
74
|
+
|
|
75
|
+
|
|
50
76
|
@dataclass(frozen=True)
|
|
51
77
|
class RecordedEvent:
|
|
52
78
|
"""
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from dataclasses import dataclass
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from typing_extensions import deprecated
|
|
6
7
|
|
|
8
|
+
from kurrentdbclient.events import StreamState
|
|
9
|
+
|
|
7
10
|
if TYPE_CHECKING:
|
|
8
11
|
from typing import Any
|
|
9
12
|
from uuid import UUID
|
|
@@ -104,15 +107,26 @@ class WrongCurrentVersionError(KurrentDBClientError):
|
|
|
104
107
|
self,
|
|
105
108
|
*args: Any,
|
|
106
109
|
stream_name: str | None = None,
|
|
107
|
-
|
|
108
|
-
expected_version: int | None = None,
|
|
110
|
+
actual_version: int | StreamState | None = None,
|
|
111
|
+
expected_version: int | StreamState | None = None,
|
|
109
112
|
) -> None:
|
|
110
113
|
self.stream_name = stream_name
|
|
111
|
-
self.
|
|
112
|
-
|
|
114
|
+
self.actual_version = MAPPING_INT_TO_STREAM_STATE.get(
|
|
115
|
+
actual_version, actual_version
|
|
116
|
+
)
|
|
117
|
+
self.expected_version = MAPPING_INT_TO_STREAM_STATE.get(
|
|
118
|
+
expected_version, expected_version
|
|
119
|
+
)
|
|
113
120
|
super().__init__(*args)
|
|
114
121
|
|
|
115
122
|
|
|
123
|
+
MAPPING_INT_TO_STREAM_STATE: dict[int | StreamState | None, StreamState] = {
|
|
124
|
+
-1: StreamState.NO_STREAM,
|
|
125
|
+
-2: StreamState.ANY,
|
|
126
|
+
-4: StreamState.EXISTS,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
116
130
|
class AccessDeniedError(KurrentDBClientError):
|
|
117
131
|
"""
|
|
118
132
|
Raised when access is denied by the server.
|
|
@@ -331,3 +345,28 @@ class InvalidCommitPositionError(KurrentDBClientError):
|
|
|
331
345
|
"""
|
|
332
346
|
Raised when reading from an commit position that does not exist.
|
|
333
347
|
"""
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
class ConsistencyChecksFailedError(KurrentDBClientError):
|
|
351
|
+
"""
|
|
352
|
+
Raised when appending records with a consistency check that fails.
|
|
353
|
+
"""
|
|
354
|
+
|
|
355
|
+
def __init__(
|
|
356
|
+
self, *args: Any, failures: tuple[ConsistencyCheckFailure, ...]
|
|
357
|
+
) -> None:
|
|
358
|
+
self.failures = failures
|
|
359
|
+
super().__init__(*args)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
@dataclass(frozen=True)
|
|
363
|
+
class ConsistencyCheckFailure:
|
|
364
|
+
check_index: int
|
|
365
|
+
stream_state_failure: StreamStateCheckFailure | None
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
@dataclass(frozen=True)
|
|
369
|
+
class StreamStateCheckFailure:
|
|
370
|
+
stream_name: str
|
|
371
|
+
expected_state: int
|
|
372
|
+
actual_state: int
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
5
5
|
|
|
6
6
|
import grpc
|
|
7
7
|
import grpc.aio
|
|
@@ -68,17 +68,34 @@ class BaseProjectionsService(KurrentDBService[TGrpcStreamers]):
|
|
|
68
68
|
@staticmethod
|
|
69
69
|
def _construct_create_req(
|
|
70
70
|
*,
|
|
71
|
-
query: str,
|
|
72
71
|
name: str,
|
|
72
|
+
query: str,
|
|
73
|
+
engine_version: Literal["v1", "v2"],
|
|
73
74
|
emit_enabled: bool,
|
|
74
75
|
track_emitted_streams: bool,
|
|
75
76
|
) -> projections_pb2.CreateReq:
|
|
77
|
+
# Decide engine version.
|
|
78
|
+
if engine_version == "v1":
|
|
79
|
+
engine_version_option = 0
|
|
80
|
+
elif engine_version == "v2": # pragma: <26.1 no cover
|
|
81
|
+
engine_version_option = 1
|
|
82
|
+
else:
|
|
83
|
+
msg = (
|
|
84
|
+
f"Unsupported projection engine version "
|
|
85
|
+
f"(hint: use 'v1' or 'v2'): {engine_version}"
|
|
86
|
+
)
|
|
87
|
+
raise ValueError(msg)
|
|
88
|
+
# Defend server against invalid requests.
|
|
89
|
+
if engine_version == "v2" and track_emitted_streams: # pragma: <26.1 no cover
|
|
90
|
+
msg = "Tracking emitted streams is not supported with engine version 2."
|
|
91
|
+
raise ValueError(msg)
|
|
76
92
|
options = projections_pb2.CreateReq.Options(
|
|
77
93
|
continuous=projections_pb2.CreateReq.Options.Continuous(
|
|
78
94
|
name=name,
|
|
79
95
|
emit_enabled=emit_enabled,
|
|
80
96
|
track_emitted_streams=track_emitted_streams,
|
|
81
97
|
),
|
|
98
|
+
engine_version=engine_version_option,
|
|
82
99
|
query=query,
|
|
83
100
|
)
|
|
84
101
|
return projections_pb2.CreateReq(options=options)
|
|
@@ -261,8 +278,9 @@ class AsyncProjectionsService(BaseProjectionsService[AsyncGrpcStreamers]):
|
|
|
261
278
|
async def create(
|
|
262
279
|
self,
|
|
263
280
|
*,
|
|
264
|
-
query: str,
|
|
265
281
|
name: str,
|
|
282
|
+
query: str,
|
|
283
|
+
engine_version: Literal["v1", "v2"],
|
|
266
284
|
emit_enabled: bool,
|
|
267
285
|
track_emitted_streams: bool,
|
|
268
286
|
timeout: float | None = None,
|
|
@@ -270,8 +288,9 @@ class AsyncProjectionsService(BaseProjectionsService[AsyncGrpcStreamers]):
|
|
|
270
288
|
credentials: grpc.CallCredentials | None = None,
|
|
271
289
|
) -> None:
|
|
272
290
|
create_req = self._construct_create_req(
|
|
273
|
-
query=query,
|
|
274
291
|
name=name,
|
|
292
|
+
query=query,
|
|
293
|
+
engine_version=engine_version,
|
|
275
294
|
emit_enabled=emit_enabled,
|
|
276
295
|
track_emitted_streams=track_emitted_streams,
|
|
277
296
|
)
|
|
@@ -541,8 +560,9 @@ class ProjectionsService(BaseProjectionsService[GrpcStreamers]):
|
|
|
541
560
|
def create(
|
|
542
561
|
self,
|
|
543
562
|
*,
|
|
544
|
-
query: str,
|
|
545
563
|
name: str,
|
|
564
|
+
query: str,
|
|
565
|
+
engine_version: Literal["v1", "v2"] = "v1",
|
|
546
566
|
emit_enabled: bool,
|
|
547
567
|
track_emitted_streams: bool,
|
|
548
568
|
timeout: float | None = None,
|
|
@@ -550,8 +570,9 @@ class ProjectionsService(BaseProjectionsService[GrpcStreamers]):
|
|
|
550
570
|
credentials: grpc.CallCredentials | None = None,
|
|
551
571
|
) -> None:
|
|
552
572
|
create_req = self._construct_create_req(
|
|
553
|
-
query=query,
|
|
554
573
|
name=name,
|
|
574
|
+
query=query,
|
|
575
|
+
engine_version=engine_version,
|
|
555
576
|
emit_enabled=emit_enabled,
|
|
556
577
|
track_emitted_streams=track_emitted_streams,
|
|
557
578
|
)
|
{kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/google/rpc/code_pb2.pyi
RENAMED
|
@@ -16,25 +16,25 @@ See the License for the specific language governing permissions and
|
|
|
16
16
|
limitations under the License.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
import
|
|
19
|
+
from google.protobuf import descriptor as _descriptor
|
|
20
|
+
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
|
|
21
|
+
import builtins as _builtins
|
|
22
22
|
import sys
|
|
23
|
-
import typing
|
|
23
|
+
import typing as _typing
|
|
24
24
|
|
|
25
25
|
if sys.version_info >= (3, 10):
|
|
26
|
-
|
|
26
|
+
from typing import TypeAlias as _TypeAlias
|
|
27
27
|
else:
|
|
28
|
-
import
|
|
28
|
+
from typing_extensions import TypeAlias as _TypeAlias
|
|
29
29
|
|
|
30
|
-
DESCRIPTOR:
|
|
30
|
+
DESCRIPTOR: _descriptor.FileDescriptor
|
|
31
31
|
|
|
32
32
|
class _Code:
|
|
33
|
-
ValueType =
|
|
34
|
-
V:
|
|
33
|
+
ValueType = _typing.NewType("ValueType", _builtins.int)
|
|
34
|
+
V: _TypeAlias = ValueType # noqa: Y015
|
|
35
35
|
|
|
36
|
-
class _CodeEnumTypeWrapper(
|
|
37
|
-
DESCRIPTOR:
|
|
36
|
+
class _CodeEnumTypeWrapper(_enum_type_wrapper._EnumTypeWrapper[_Code.ValueType], _builtins.type):
|
|
37
|
+
DESCRIPTOR: _descriptor.EnumDescriptor
|
|
38
38
|
OK: _Code.ValueType # 0
|
|
39
39
|
"""Not an error; returned on success.
|
|
40
40
|
|
|
@@ -354,4 +354,4 @@ DATA_LOSS: Code.ValueType # 15
|
|
|
354
354
|
|
|
355
355
|
HTTP Mapping: 500 Internal Server Error
|
|
356
356
|
"""
|
|
357
|
-
|
|
357
|
+
Global___Code: _TypeAlias = Code # noqa: Y015
|
{kurrentdbclient-1.2.3 → kurrentdbclient-1.3.0}/kurrentdbclient/protos/google/rpc/code_pb2_grpc.py
RENAMED
|
@@ -4,7 +4,7 @@ import grpc
|
|
|
4
4
|
import warnings
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
GRPC_GENERATED_VERSION = '1.
|
|
7
|
+
GRPC_GENERATED_VERSION = '1.80.0'
|
|
8
8
|
GRPC_VERSION = grpc.__version__
|
|
9
9
|
_version_not_supported = False
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ except ImportError:
|
|
|
17
17
|
if _version_not_supported:
|
|
18
18
|
raise RuntimeError(
|
|
19
19
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
20
|
-
+
|
|
20
|
+
+ ' but the generated code in kurrentdbclient/protos/google/rpc/code_pb2_grpc.py depends on'
|
|
21
21
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
22
22
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
23
23
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|