kurrentdbclient 0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. kurrentdbclient/__init__.py +49 -0
  2. kurrentdbclient/asyncio_client.py +1662 -0
  3. kurrentdbclient/client.py +1914 -0
  4. kurrentdbclient/common.py +535 -0
  5. kurrentdbclient/connection.py +107 -0
  6. kurrentdbclient/connection_spec.py +371 -0
  7. kurrentdbclient/events.py +141 -0
  8. kurrentdbclient/exceptions.py +239 -0
  9. kurrentdbclient/gossip.py +104 -0
  10. kurrentdbclient/instrumentation/__init__.py +0 -0
  11. kurrentdbclient/instrumentation/opentelemetry/__init__.py +185 -0
  12. kurrentdbclient/instrumentation/opentelemetry/attributes.py +20 -0
  13. kurrentdbclient/instrumentation/opentelemetry/grpc.py +165 -0
  14. kurrentdbclient/instrumentation/opentelemetry/package.py +2 -0
  15. kurrentdbclient/instrumentation/opentelemetry/spanners.py +1097 -0
  16. kurrentdbclient/instrumentation/opentelemetry/utils.py +199 -0
  17. kurrentdbclient/instrumentation/opentelemetry/version.py +2 -0
  18. kurrentdbclient/persistent.py +1982 -0
  19. kurrentdbclient/projections.py +735 -0
  20. kurrentdbclient/protos/Grpc/cluster_pb2.py +92 -0
  21. kurrentdbclient/protos/Grpc/cluster_pb2.pyi +765 -0
  22. kurrentdbclient/protos/Grpc/cluster_pb2_grpc.py +514 -0
  23. kurrentdbclient/protos/Grpc/code_pb2.py +37 -0
  24. kurrentdbclient/protos/Grpc/code_pb2.pyi +357 -0
  25. kurrentdbclient/protos/Grpc/code_pb2_grpc.py +24 -0
  26. kurrentdbclient/protos/Grpc/gossip_pb2.py +46 -0
  27. kurrentdbclient/protos/Grpc/gossip_pb2.pyi +126 -0
  28. kurrentdbclient/protos/Grpc/gossip_pb2_grpc.py +98 -0
  29. kurrentdbclient/protos/Grpc/persistent_pb2.py +140 -0
  30. kurrentdbclient/protos/Grpc/persistent_pb2.pyi +1135 -0
  31. kurrentdbclient/protos/Grpc/persistent_pb2_grpc.py +399 -0
  32. kurrentdbclient/protos/Grpc/projections_pb2.py +99 -0
  33. kurrentdbclient/protos/Grpc/projections_pb2.pyi +558 -0
  34. kurrentdbclient/protos/Grpc/projections_pb2_grpc.py +485 -0
  35. kurrentdbclient/protos/Grpc/shared_pb2.py +62 -0
  36. kurrentdbclient/protos/Grpc/shared_pb2.pyi +218 -0
  37. kurrentdbclient/protos/Grpc/shared_pb2_grpc.py +24 -0
  38. kurrentdbclient/protos/Grpc/status_pb2.py +39 -0
  39. kurrentdbclient/protos/Grpc/status_pb2.pyi +67 -0
  40. kurrentdbclient/protos/Grpc/status_pb2_grpc.py +24 -0
  41. kurrentdbclient/protos/Grpc/streams_pb2.py +132 -0
  42. kurrentdbclient/protos/Grpc/streams_pb2.pyi +1038 -0
  43. kurrentdbclient/protos/Grpc/streams_pb2_grpc.py +269 -0
  44. kurrentdbclient/py.typed +0 -0
  45. kurrentdbclient/streams.py +1400 -0
  46. kurrentdbclient-0.3.dist-info/LICENSE +29 -0
  47. kurrentdbclient-0.3.dist-info/METADATA +3769 -0
  48. kurrentdbclient-0.3.dist-info/RECORD +49 -0
  49. kurrentdbclient-0.3.dist-info/WHEEL +4 -0
@@ -0,0 +1,1662 @@
1
+ # -*- coding: utf-8 -*-
2
+ from __future__ import annotations
3
+
4
+ import asyncio
5
+ import json
6
+ import sys
7
+ from asyncio import Event, Lock
8
+ from functools import wraps
9
+ from typing import (
10
+ Any,
11
+ Callable,
12
+ Dict,
13
+ Iterable,
14
+ Optional,
15
+ Sequence,
16
+ Tuple,
17
+ TypeVar,
18
+ Union,
19
+ cast,
20
+ overload,
21
+ )
22
+ from warnings import warn
23
+
24
+ import grpc.aio
25
+ from typing_extensions import Literal
26
+
27
+ from kurrentdbclient.client import DEFAULT_EXCLUDE_FILTER, BaseKurrentDBClient
28
+ from kurrentdbclient.common import (
29
+ DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
30
+ DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
31
+ DEFAULT_PERSISTENT_SUBSCRIPTION_EVENT_BUFFER_SIZE,
32
+ DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
33
+ DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
34
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_ACK_BATCH_SIZE,
35
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_ACK_DELAY,
36
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
37
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
38
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
39
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
40
+ DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
41
+ DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
42
+ DEFAULT_PERSISTENT_SUBSCRIPTION_STOPPING_GRACE,
43
+ DEFAULT_WINDOW_SIZE,
44
+ AbstractAsyncCatchupSubscription,
45
+ AbstractAsyncPersistentSubscription,
46
+ GrpcOptions,
47
+ )
48
+ from kurrentdbclient.connection import AsyncKurrentDBConnection
49
+ from kurrentdbclient.connection_spec import (
50
+ NODE_PREFERENCE_LEADER,
51
+ URI_SCHEMES_NON_DISCOVER,
52
+ )
53
+ from kurrentdbclient.events import NewEvent, RecordedEvent
54
+ from kurrentdbclient.exceptions import (
55
+ DeadlineExceeded,
56
+ DiscoveryFailed,
57
+ GrpcError,
58
+ NodeIsNotLeader,
59
+ NotFound,
60
+ ServiceUnavailable,
61
+ )
62
+ from kurrentdbclient.persistent import ConsumerStrategy, SubscriptionInfo
63
+ from kurrentdbclient.projections import ProjectionState, ProjectionStatistics
64
+ from kurrentdbclient.streams import AsyncReadResponse, StreamState
65
+
66
+ _TCallable = TypeVar("_TCallable", bound=Callable[..., Any])
67
+
68
+
69
+ def autoreconnect(f: _TCallable) -> _TCallable:
70
+ @wraps(f)
71
+ async def autoreconnect_decorator(
72
+ client: "AsyncKurrentDBClient", *args: Any, **kwargs: Any
73
+ ) -> Any:
74
+ try:
75
+ return await f(client, *args, **kwargs)
76
+
77
+ except NodeIsNotLeader as e:
78
+ if (
79
+ client.connection_spec.options.NodePreference == NODE_PREFERENCE_LEADER
80
+ and not (
81
+ client.connection_spec.scheme in URI_SCHEMES_NON_DISCOVER
82
+ and len(client.connection_spec.targets) == 1
83
+ )
84
+ ):
85
+ await client.reconnect(e.leader_grpc_target)
86
+ await asyncio.sleep(0.1)
87
+ return await f(client, *args, **kwargs)
88
+ else:
89
+ raise
90
+
91
+ except grpc.aio.UsageError as e:
92
+ if "Channel is closed" in str(e):
93
+ await client.reconnect()
94
+ await asyncio.sleep(0.1)
95
+ return await f(client, *args, **kwargs)
96
+ else: # pragma: no cover
97
+ raise
98
+
99
+ except ServiceUnavailable:
100
+ await client.reconnect()
101
+ await asyncio.sleep(0.1)
102
+ return await f(client, *args, **kwargs)
103
+
104
+ return cast(_TCallable, autoreconnect_decorator)
105
+
106
+
107
+ def retrygrpc(f: _TCallable) -> _TCallable:
108
+ @wraps(f)
109
+ async def retrygrpc_decorator(*args: Any, **kwargs: Any) -> Any:
110
+ try:
111
+ return await f(*args, **kwargs)
112
+ except GrpcError:
113
+ await asyncio.sleep(0.1)
114
+ return await f(*args, **kwargs)
115
+
116
+ return cast(_TCallable, retrygrpc_decorator)
117
+
118
+
119
+ async def AsyncioKurrentDBClient(
120
+ uri: str, root_certificates: Optional[Union[str, bytes]] = None
121
+ ) -> _AsyncioKurrentDBClient:
122
+ warn(
123
+ (
124
+ "async function 'AsyncioKurrentDBClient' is deprecated. "
125
+ "Instead, please construct an instance of class 'AsyncKurrentDBClient' "
126
+ "and await a call to async method AsyncKurrentDBClient.connect()."
127
+ ),
128
+ DeprecationWarning,
129
+ stacklevel=2,
130
+ )
131
+
132
+ client = _AsyncioKurrentDBClient(uri=uri, root_certificates=root_certificates)
133
+ await client.connect()
134
+ return client
135
+
136
+
137
+ class AsyncKurrentDBClient(BaseKurrentDBClient):
138
+ def __init__(
139
+ self,
140
+ uri: str,
141
+ root_certificates: Optional[Union[str, bytes]] = None,
142
+ private_key: Optional[Union[str, bytes]] = None,
143
+ certificate_chain: Optional[Union[str, bytes]] = None,
144
+ ):
145
+ super().__init__(
146
+ uri=uri,
147
+ root_certificates=root_certificates,
148
+ private_key=private_key,
149
+ certificate_chain=certificate_chain,
150
+ )
151
+ self._is_reconnection_required = Event()
152
+ self._reconnection_lock = Lock()
153
+
154
+ @property
155
+ def connection_target(self) -> str:
156
+ return self._connection.grpc_target
157
+
158
+ async def connect(self) -> None:
159
+ self._connection = await self._connect()
160
+
161
+ async def reconnect(self, grpc_target: Optional[str] = None) -> None:
162
+ self._is_reconnection_required.set()
163
+ async with self._reconnection_lock:
164
+ if self._is_reconnection_required.is_set():
165
+ new = await self._connect(grpc_target)
166
+ old, self._connection = self._connection, new
167
+ await old.close()
168
+ self._is_reconnection_required.clear()
169
+ else: # pragma: no cover
170
+ # Todo: Test with concurrent writes to wrong node state.
171
+ pass
172
+
173
+ async def _connect(
174
+ self, grpc_target: Optional[str] = None
175
+ ) -> AsyncKurrentDBConnection:
176
+ if grpc_target:
177
+ # Just connect to the given target.
178
+ return self._construct_esdb_connection(grpc_target)
179
+ if (
180
+ self.connection_spec.scheme in URI_SCHEMES_NON_DISCOVER
181
+ and len(self.connection_spec.targets) == 1
182
+ ):
183
+ # Just connect to the specified target.
184
+ return self._construct_esdb_connection(
185
+ grpc_target=self.connection_spec.targets[0],
186
+ )
187
+ # Discover preferred node in cluster.
188
+ return await self._discover_preferred_node()
189
+
190
+ async def _discover_preferred_node(self) -> AsyncKurrentDBConnection:
191
+ attempts = self.connection_spec.options.MaxDiscoverAttempts
192
+ assert attempts > 0
193
+ if self.connection_spec.scheme in URI_SCHEMES_NON_DISCOVER:
194
+ grpc_options: GrpcOptions = ()
195
+ else:
196
+ grpc_options = (("grpc.lb_policy_name", "round_robin"),)
197
+ while True:
198
+ # Attempt to discover preferred node.
199
+ try:
200
+ last_exception: Optional[Exception] = None
201
+ for grpc_target in self.connection_spec.targets:
202
+ connection = self._construct_esdb_connection(
203
+ grpc_target=grpc_target,
204
+ grpc_options=grpc_options,
205
+ )
206
+ try:
207
+ cluster_members = await connection.gossip.read(
208
+ timeout=self.connection_spec.options.GossipTimeout,
209
+ metadata=self._call_metadata,
210
+ credentials=self._call_credentials,
211
+ )
212
+ except (GrpcError, DeadlineExceeded) as e:
213
+ last_exception = e
214
+ await connection.close()
215
+ else:
216
+ break
217
+ else:
218
+ msg = (
219
+ "Failed to obtain cluster info from"
220
+ f" '{','.join(self.connection_spec.targets)}':"
221
+ f" {str(last_exception)}"
222
+ )
223
+ raise DiscoveryFailed(msg) from last_exception
224
+
225
+ preferred_member = self._select_preferred_member(cluster_members)
226
+
227
+ except DiscoveryFailed:
228
+ attempts -= 1
229
+ if attempts == 0:
230
+ raise
231
+ else:
232
+ await asyncio.sleep(
233
+ self.connection_spec.options.DiscoveryInterval / 1000
234
+ )
235
+ else:
236
+ break
237
+
238
+ # Maybe close connection and connect to preferred node.
239
+ if len(cluster_members) > 1: # forgive not "advertising" single node
240
+ preferred_target = f"{preferred_member.address}:{preferred_member.port}"
241
+ if preferred_target != connection.grpc_target:
242
+ await connection.close()
243
+ connection = self._construct_esdb_connection(preferred_target)
244
+
245
+ return connection
246
+
247
+ def _construct_esdb_connection(
248
+ self, grpc_target: str, grpc_options: GrpcOptions = ()
249
+ ) -> AsyncKurrentDBConnection:
250
+ grpc_options = self.grpc_options + grpc_options
251
+ if self.connection_spec.options.Tls is True:
252
+ channel_credentials = grpc.ssl_channel_credentials(
253
+ root_certificates=self.root_certificates,
254
+ private_key=self.private_key,
255
+ certificate_chain=self.certificate_chain,
256
+ )
257
+ grpc_channel = grpc.aio.secure_channel(
258
+ target=grpc_target,
259
+ credentials=channel_credentials,
260
+ options=grpc_options,
261
+ )
262
+ else:
263
+ grpc_channel = grpc.aio.insecure_channel(
264
+ target=grpc_target, options=grpc_options
265
+ )
266
+
267
+ return AsyncKurrentDBConnection(
268
+ grpc_channel=grpc_channel,
269
+ grpc_target=grpc_target,
270
+ connection_spec=self.connection_spec,
271
+ )
272
+
273
+ async def append_events(
274
+ self,
275
+ stream_name: str,
276
+ *,
277
+ current_version: Union[int, StreamState],
278
+ events: Iterable[NewEvent],
279
+ timeout: Optional[float] = None,
280
+ credentials: Optional[grpc.CallCredentials] = None,
281
+ ) -> int:
282
+ return await self.append_to_stream(
283
+ stream_name=stream_name,
284
+ current_version=current_version,
285
+ events=events,
286
+ timeout=timeout,
287
+ credentials=credentials,
288
+ )
289
+
290
+ @retrygrpc
291
+ @autoreconnect
292
+ async def append_to_stream(
293
+ self,
294
+ stream_name: str,
295
+ *,
296
+ current_version: Union[int, StreamState],
297
+ events: Union[NewEvent, Iterable[NewEvent]],
298
+ timeout: Optional[float] = None,
299
+ credentials: Optional[grpc.CallCredentials] = None,
300
+ ) -> int:
301
+ timeout = timeout if timeout is not None else self._default_deadline
302
+
303
+ if isinstance(events, NewEvent):
304
+ events = [events]
305
+
306
+ return await self._connection.streams.batch_append(
307
+ stream_name=stream_name,
308
+ current_version=current_version,
309
+ events=events,
310
+ timeout=timeout,
311
+ metadata=self._call_metadata,
312
+ credentials=credentials or self._call_credentials,
313
+ )
314
+
315
+ @retrygrpc
316
+ @autoreconnect
317
+ async def read_all(
318
+ self,
319
+ *,
320
+ commit_position: Optional[int] = None,
321
+ backwards: bool = False,
322
+ resolve_links: bool = False,
323
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
324
+ filter_include: Sequence[str] = (),
325
+ filter_by_stream_name: bool = False,
326
+ limit: int = sys.maxsize,
327
+ timeout: Optional[float] = None,
328
+ credentials: Optional[grpc.CallCredentials] = None,
329
+ ) -> AsyncReadResponse:
330
+ """
331
+ Reads recorded events in "all streams" in the database.
332
+ """
333
+ return await self._connection.streams.read(
334
+ commit_position=commit_position,
335
+ backwards=backwards,
336
+ resolve_links=resolve_links,
337
+ filter_exclude=filter_exclude,
338
+ filter_include=filter_include,
339
+ filter_by_stream_name=filter_by_stream_name,
340
+ limit=limit,
341
+ timeout=timeout,
342
+ metadata=self._call_metadata,
343
+ credentials=credentials or self._call_credentials,
344
+ )
345
+
346
+ @retrygrpc
347
+ @autoreconnect
348
+ async def get_commit_position(
349
+ self,
350
+ *,
351
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
352
+ filter_include: Sequence[str] = (),
353
+ filter_by_stream_name: bool = False,
354
+ timeout: Optional[float] = None,
355
+ credentials: Optional[grpc.CallCredentials] = None,
356
+ ) -> int:
357
+ """
358
+ Returns the current commit position of the database.
359
+ """
360
+ recorded_events = await self.read_all(
361
+ backwards=True,
362
+ filter_exclude=filter_exclude,
363
+ filter_include=filter_include,
364
+ filter_by_stream_name=filter_by_stream_name,
365
+ limit=1,
366
+ timeout=timeout,
367
+ credentials=credentials,
368
+ )
369
+ async for ev in recorded_events:
370
+ assert ev.commit_position is not None
371
+ commit_position = ev.commit_position
372
+ break
373
+ else:
374
+ commit_position = 0
375
+ return commit_position
376
+
377
+ @retrygrpc
378
+ @autoreconnect
379
+ async def get_stream(
380
+ self,
381
+ stream_name: str,
382
+ *,
383
+ stream_position: Optional[int] = None,
384
+ backwards: bool = False,
385
+ resolve_links: bool = False,
386
+ limit: int = sys.maxsize,
387
+ timeout: Optional[float] = None,
388
+ credentials: Optional[grpc.CallCredentials] = None,
389
+ ) -> Sequence[RecordedEvent]:
390
+ """
391
+ Lists recorded events from the named stream.
392
+ """
393
+ async with await self.read_stream(
394
+ stream_name=stream_name,
395
+ stream_position=stream_position,
396
+ backwards=backwards,
397
+ resolve_links=resolve_links,
398
+ limit=limit,
399
+ timeout=timeout,
400
+ credentials=credentials or self._call_credentials,
401
+ ) as events:
402
+ return tuple([e async for e in events])
403
+
404
+ @retrygrpc
405
+ @autoreconnect
406
+ async def read_stream(
407
+ self,
408
+ stream_name: str,
409
+ *,
410
+ stream_position: Optional[int] = None,
411
+ backwards: bool = False,
412
+ resolve_links: bool = False,
413
+ limit: int = sys.maxsize,
414
+ timeout: Optional[float] = None,
415
+ credentials: Optional[grpc.CallCredentials] = None,
416
+ ) -> AsyncReadResponse:
417
+ """
418
+ Reads recorded events from the named stream.
419
+ """
420
+ return await self._connection.streams.read(
421
+ stream_name=stream_name,
422
+ stream_position=stream_position,
423
+ backwards=backwards,
424
+ resolve_links=resolve_links,
425
+ limit=limit,
426
+ timeout=timeout,
427
+ metadata=self._call_metadata,
428
+ credentials=credentials or self._call_credentials,
429
+ )
430
+
431
+ @retrygrpc
432
+ @autoreconnect
433
+ async def get_stream_metadata(
434
+ self,
435
+ stream_name: str,
436
+ *,
437
+ timeout: Optional[float] = None,
438
+ credentials: Optional[grpc.CallCredentials] = None,
439
+ ) -> Tuple[Dict[str, Any], Union[int, Literal[StreamState.NO_STREAM]]]:
440
+ """
441
+ Gets the stream metadata.
442
+ """
443
+ metadata_stream_name = f"$${stream_name}"
444
+ try:
445
+ metadata_events = await self.get_stream(
446
+ stream_name=metadata_stream_name,
447
+ backwards=True,
448
+ limit=1,
449
+ timeout=timeout,
450
+ credentials=credentials or self._call_credentials,
451
+ )
452
+ except NotFound:
453
+ return {}, StreamState.NO_STREAM
454
+ else:
455
+ metadata_event = metadata_events[0]
456
+ return json.loads(metadata_event.data), metadata_event.stream_position
457
+
458
+ async def set_stream_metadata(
459
+ self,
460
+ stream_name: str,
461
+ *,
462
+ metadata: Dict[str, Any],
463
+ current_version: Union[int, StreamState] = StreamState.ANY,
464
+ timeout: Optional[float] = None,
465
+ credentials: Optional[grpc.CallCredentials] = None,
466
+ ) -> None:
467
+ """
468
+ Sets the stream metadata.
469
+ """
470
+ timeout = timeout if timeout is not None else self._default_deadline
471
+
472
+ metadata_stream_name = f"$${stream_name}"
473
+ metadata_event = NewEvent(
474
+ type="$metadata",
475
+ data=json.dumps(metadata).encode("utf8"),
476
+ )
477
+ await self.append_events(
478
+ stream_name=metadata_stream_name,
479
+ current_version=current_version,
480
+ events=[metadata_event],
481
+ timeout=timeout,
482
+ credentials=credentials or self._call_credentials,
483
+ )
484
+
485
+ @retrygrpc
486
+ @autoreconnect
487
+ async def subscribe_to_all(
488
+ self,
489
+ *,
490
+ commit_position: Optional[int] = None,
491
+ from_end: bool = False,
492
+ resolve_links: bool = False,
493
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
494
+ filter_include: Sequence[str] = (),
495
+ filter_by_stream_name: bool = False,
496
+ include_checkpoints: bool = False,
497
+ window_size: int = DEFAULT_WINDOW_SIZE,
498
+ checkpoint_interval_multiplier: int = DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
499
+ include_caught_up: bool = False,
500
+ timeout: Optional[float] = None,
501
+ credentials: Optional[grpc.CallCredentials] = None,
502
+ ) -> AbstractAsyncCatchupSubscription:
503
+ """
504
+ Starts a catch-up subscription, from which all
505
+ recorded events in the database can be received.
506
+ """
507
+ return await self._connection.streams.read(
508
+ commit_position=commit_position,
509
+ from_end=from_end,
510
+ resolve_links=resolve_links,
511
+ filter_exclude=filter_exclude,
512
+ filter_include=filter_include,
513
+ filter_by_stream_name=filter_by_stream_name,
514
+ subscribe=True,
515
+ include_checkpoints=include_checkpoints,
516
+ window_size=window_size,
517
+ checkpoint_interval_multiplier=checkpoint_interval_multiplier,
518
+ include_caught_up=include_caught_up,
519
+ timeout=timeout,
520
+ metadata=self._call_metadata,
521
+ credentials=credentials or self._call_credentials,
522
+ )
523
+
524
+ #
525
+ # @overload
526
+ # async def subscribe_to_stream(
527
+ # self,
528
+ # stream_name: str,
529
+ # *,
530
+ # resolve_links: bool = False,
531
+ # include_caught_up: bool = False,
532
+ # timeout: Optional[float] = None,
533
+ # credentials: Optional[grpc.CallCredentials] = None,
534
+ # ) -> AsyncCatchupSubscription:
535
+ # """
536
+ # Signature to start catch-up subscription from the start of the stream.
537
+ # """
538
+ #
539
+ # @overload
540
+ # async def subscribe_to_stream(
541
+ # self,
542
+ # stream_name: str,
543
+ # *,
544
+ # stream_position: int,
545
+ # resolve_links: bool = False,
546
+ # include_caught_up: bool = False,
547
+ # timeout: Optional[float] = None,
548
+ # credentials: Optional[grpc.CallCredentials] = None,
549
+ # ) -> AsyncCatchupSubscription:
550
+ # """
551
+ # Signature to start catch-up subscription from a particular stream position.
552
+ # """
553
+ #
554
+ # @overload
555
+ # async def subscribe_to_stream(
556
+ # self,
557
+ # stream_name: str,
558
+ # *,
559
+ # from_end: Literal[True] = True,
560
+ # resolve_links: bool = False,
561
+ # include_caught_up: bool = False,
562
+ # timeout: Optional[float] = None,
563
+ # credentials: Optional[grpc.CallCredentials] = None,
564
+ # ) -> AsyncCatchupSubscription:
565
+ # """
566
+ # Signature to start catch-up subscription from the end of the stream.
567
+ # """
568
+
569
+ @retrygrpc
570
+ @autoreconnect
571
+ async def subscribe_to_stream(
572
+ self,
573
+ stream_name: str,
574
+ *,
575
+ stream_position: Optional[int] = None,
576
+ from_end: bool = False,
577
+ resolve_links: bool = False,
578
+ include_caught_up: bool = False,
579
+ timeout: Optional[float] = None,
580
+ credentials: Optional[grpc.CallCredentials] = None,
581
+ ) -> AbstractAsyncCatchupSubscription:
582
+ """
583
+ Starts a catch-up subscription from which
584
+ recorded events in a stream can be received.
585
+ """
586
+ return await self._connection.streams.read(
587
+ stream_name=stream_name,
588
+ stream_position=stream_position,
589
+ from_end=from_end,
590
+ resolve_links=resolve_links,
591
+ subscribe=True,
592
+ include_caught_up=include_caught_up,
593
+ timeout=timeout,
594
+ metadata=self._call_metadata,
595
+ credentials=credentials or self._call_credentials,
596
+ )
597
+
598
+ @retrygrpc
599
+ @autoreconnect
600
+ async def delete_stream(
601
+ self,
602
+ stream_name: str,
603
+ *,
604
+ current_version: Union[int, StreamState],
605
+ timeout: Optional[float] = None,
606
+ credentials: Optional[grpc.CallCredentials] = None,
607
+ ) -> None:
608
+ # Todo: Reconsider using current_version=None to indicate "stream exists"?
609
+ timeout = timeout if timeout is not None else self._default_deadline
610
+ await self._connection.streams.delete(
611
+ stream_name=stream_name,
612
+ current_version=current_version,
613
+ timeout=timeout,
614
+ metadata=self._call_metadata,
615
+ credentials=credentials or self._call_credentials,
616
+ )
617
+
618
+ @retrygrpc
619
+ @autoreconnect
620
+ async def tombstone_stream(
621
+ self,
622
+ stream_name: str,
623
+ *,
624
+ current_version: Union[int, StreamState],
625
+ timeout: Optional[float] = None,
626
+ credentials: Optional[grpc.CallCredentials] = None,
627
+ ) -> None:
628
+ timeout = timeout if timeout is not None else self._default_deadline
629
+ await self._connection.streams.tombstone(
630
+ stream_name=stream_name,
631
+ current_version=current_version,
632
+ timeout=timeout,
633
+ metadata=self._call_metadata,
634
+ credentials=credentials or self._call_credentials,
635
+ )
636
+
637
+ @retrygrpc
638
+ @autoreconnect
639
+ async def get_current_version(
640
+ self,
641
+ stream_name: str,
642
+ *,
643
+ timeout: Optional[float] = None,
644
+ credentials: Optional[grpc.CallCredentials] = None,
645
+ ) -> Union[int, Literal[StreamState.NO_STREAM]]:
646
+ """
647
+ Returns the current position of the end of a stream.
648
+ """
649
+ try:
650
+ last_event = [
651
+ e
652
+ async for e in await self._connection.streams.read(
653
+ stream_name=stream_name,
654
+ backwards=True,
655
+ limit=1,
656
+ timeout=timeout,
657
+ metadata=self._call_metadata,
658
+ credentials=credentials or self._call_credentials,
659
+ )
660
+ ][0]
661
+ except NotFound:
662
+ # StreamState.NO_STREAM is the correct "current version" both when appending
663
+ # to a stream that never existed and when appending to a stream that has
664
+ # been deleted (in this case of a deleted stream, the "current version"
665
+ # before deletion is also correct).
666
+ return StreamState.NO_STREAM
667
+ else:
668
+ return last_event.stream_position
669
+
670
+ @overload
671
+ async def create_subscription_to_all(
672
+ self,
673
+ group_name: str,
674
+ *,
675
+ resolve_links: bool = False,
676
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
677
+ filter_include: Sequence[str] = (),
678
+ filter_by_stream_name: bool = False,
679
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
680
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
681
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
682
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
683
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
684
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
685
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
686
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
687
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
688
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
689
+ extra_statistics: bool = False,
690
+ timeout: Optional[float] = None,
691
+ credentials: Optional[grpc.CallCredentials] = None,
692
+ ) -> None:
693
+ """
694
+ Signature for creating persistent subscription from start of database.
695
+ """
696
+
697
+ @overload
698
+ async def create_subscription_to_all(
699
+ self,
700
+ group_name: str,
701
+ *,
702
+ commit_position: int,
703
+ resolve_links: bool = False,
704
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
705
+ filter_include: Sequence[str] = (),
706
+ filter_by_stream_name: bool = False,
707
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
708
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
709
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
710
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
711
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
712
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
713
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
714
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
715
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
716
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
717
+ extra_statistics: bool = False,
718
+ timeout: Optional[float] = None,
719
+ credentials: Optional[grpc.CallCredentials] = None,
720
+ ) -> None:
721
+ """
722
+ Signature for creating persistent subscription from a commit position.
723
+ """
724
+
725
+ @overload
726
+ async def create_subscription_to_all(
727
+ self,
728
+ group_name: str,
729
+ *,
730
+ from_end: bool = True,
731
+ resolve_links: bool = False,
732
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
733
+ filter_include: Sequence[str] = (),
734
+ filter_by_stream_name: bool = False,
735
+ window_size: int = DEFAULT_WINDOW_SIZE,
736
+ checkpoint_interval_multiplier: int = DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
737
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
738
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
739
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
740
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
741
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
742
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
743
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
744
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
745
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
746
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
747
+ extra_statistics: bool = False,
748
+ timeout: Optional[float] = None,
749
+ credentials: Optional[grpc.CallCredentials] = None,
750
+ ) -> None:
751
+ """
752
+ Signature for creating persistent subscription from end of database.
753
+ """
754
+
755
+ @retrygrpc
756
+ @autoreconnect
757
+ async def create_subscription_to_all(
758
+ self,
759
+ group_name: str,
760
+ *,
761
+ from_end: bool = False,
762
+ commit_position: Optional[int] = None,
763
+ resolve_links: bool = False,
764
+ filter_exclude: Sequence[str] = DEFAULT_EXCLUDE_FILTER,
765
+ filter_include: Sequence[str] = (),
766
+ filter_by_stream_name: bool = False,
767
+ window_size: int = DEFAULT_WINDOW_SIZE,
768
+ checkpoint_interval_multiplier: int = DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER,
769
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
770
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
771
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
772
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
773
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
774
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
775
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
776
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
777
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
778
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
779
+ extra_statistics: bool = False,
780
+ timeout: Optional[float] = None,
781
+ credentials: Optional[grpc.CallCredentials] = None,
782
+ ) -> None:
783
+ """
784
+ Creates a persistent subscription on all streams.
785
+ """
786
+ timeout = timeout if timeout is not None else self._default_deadline
787
+
788
+ await self._connection.persistent_subscriptions.create(
789
+ group_name=group_name,
790
+ from_end=from_end,
791
+ commit_position=commit_position,
792
+ resolve_links=resolve_links,
793
+ consumer_strategy=consumer_strategy,
794
+ filter_exclude=filter_exclude,
795
+ filter_include=filter_include,
796
+ filter_by_stream_name=filter_by_stream_name,
797
+ window_size=window_size,
798
+ checkpoint_interval_multiplier=checkpoint_interval_multiplier,
799
+ message_timeout=message_timeout,
800
+ max_retry_count=max_retry_count,
801
+ min_checkpoint_count=min_checkpoint_count,
802
+ max_checkpoint_count=max_checkpoint_count,
803
+ checkpoint_after=checkpoint_after,
804
+ max_subscriber_count=max_subscriber_count,
805
+ live_buffer_size=live_buffer_size,
806
+ read_batch_size=read_batch_size,
807
+ history_buffer_size=history_buffer_size,
808
+ extra_statistics=extra_statistics,
809
+ timeout=timeout,
810
+ metadata=self._call_metadata,
811
+ credentials=credentials or self._call_credentials,
812
+ )
813
+
814
+ @overload
815
+ async def create_subscription_to_stream(
816
+ self,
817
+ group_name: str,
818
+ stream_name: str,
819
+ *,
820
+ resolve_links: bool = False,
821
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
822
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
823
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
824
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
825
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
826
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
827
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
828
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
829
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
830
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
831
+ extra_statistics: bool = False,
832
+ timeout: Optional[float] = None,
833
+ credentials: Optional[grpc.CallCredentials] = None,
834
+ ) -> None:
835
+ """
836
+ Signature for creating stream subscription from start of stream.
837
+ """
838
+
839
+ @overload
840
+ async def create_subscription_to_stream(
841
+ self,
842
+ group_name: str,
843
+ stream_name: str,
844
+ *,
845
+ stream_position: int,
846
+ resolve_links: bool = False,
847
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
848
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
849
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
850
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
851
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
852
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
853
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
854
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
855
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
856
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
857
+ extra_statistics: bool = False,
858
+ timeout: Optional[float] = None,
859
+ credentials: Optional[grpc.CallCredentials] = None,
860
+ ) -> None:
861
+ """
862
+ Signature for creating stream subscription from stream position.
863
+ """
864
+
865
+ @overload
866
+ async def create_subscription_to_stream(
867
+ self,
868
+ group_name: str,
869
+ stream_name: str,
870
+ *,
871
+ from_end: bool = True,
872
+ resolve_links: bool = False,
873
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
874
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
875
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
876
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
877
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
878
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
879
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
880
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
881
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
882
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
883
+ extra_statistics: bool = False,
884
+ timeout: Optional[float] = None,
885
+ credentials: Optional[grpc.CallCredentials] = None,
886
+ ) -> None:
887
+ """
888
+ Signature for creating stream subscription from end of stream.
889
+ """
890
+
891
+ @retrygrpc
892
+ @autoreconnect
893
+ async def create_subscription_to_stream(
894
+ self,
895
+ group_name: str,
896
+ stream_name: str,
897
+ *,
898
+ from_end: bool = False,
899
+ stream_position: Optional[int] = None,
900
+ resolve_links: bool = False,
901
+ consumer_strategy: ConsumerStrategy = "DispatchToSingle",
902
+ message_timeout: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MESSAGE_TIMEOUT,
903
+ max_retry_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_RETRY_COUNT,
904
+ min_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MIN_CHECKPOINT_COUNT,
905
+ max_checkpoint_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_CHECKPOINT_COUNT,
906
+ checkpoint_after: float = DEFAULT_PERSISTENT_SUBSCRIPTION_CHECKPOINT_AFTER,
907
+ max_subscriber_count: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_SUBSCRIBER_COUNT,
908
+ live_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_LIVE_BUFFER_SIZE,
909
+ read_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_READ_BATCH_SIZE,
910
+ history_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_HISTORY_BUFFER_SIZE,
911
+ extra_statistics: bool = False,
912
+ timeout: Optional[float] = None,
913
+ credentials: Optional[grpc.CallCredentials] = None,
914
+ ) -> None:
915
+ """
916
+ Creates a persistent subscription on one stream.
917
+ """
918
+ timeout = timeout if timeout is not None else self._default_deadline
919
+
920
+ await self._connection.persistent_subscriptions.create(
921
+ group_name=group_name,
922
+ stream_name=stream_name,
923
+ from_end=from_end,
924
+ stream_position=stream_position,
925
+ resolve_links=resolve_links,
926
+ consumer_strategy=consumer_strategy,
927
+ message_timeout=message_timeout,
928
+ max_retry_count=max_retry_count,
929
+ min_checkpoint_count=min_checkpoint_count,
930
+ max_checkpoint_count=max_checkpoint_count,
931
+ checkpoint_after=checkpoint_after,
932
+ max_subscriber_count=max_subscriber_count,
933
+ live_buffer_size=live_buffer_size,
934
+ read_batch_size=read_batch_size,
935
+ history_buffer_size=history_buffer_size,
936
+ extra_statistics=extra_statistics,
937
+ timeout=timeout,
938
+ metadata=self._call_metadata,
939
+ credentials=credentials or self._call_credentials,
940
+ )
941
+
942
+ @retrygrpc
943
+ @autoreconnect
944
+ async def read_subscription_to_all(
945
+ self,
946
+ group_name: str,
947
+ *,
948
+ event_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_EVENT_BUFFER_SIZE,
949
+ max_ack_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_ACK_BATCH_SIZE,
950
+ max_ack_delay: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_ACK_DELAY,
951
+ stopping_grace: float = DEFAULT_PERSISTENT_SUBSCRIPTION_STOPPING_GRACE,
952
+ timeout: Optional[float] = None,
953
+ credentials: Optional[grpc.CallCredentials] = None,
954
+ ) -> AbstractAsyncPersistentSubscription:
955
+ """
956
+ Reads a persistent subscription on all streams.
957
+ """
958
+ return await self._connection.persistent_subscriptions.read(
959
+ group_name=group_name,
960
+ event_buffer_size=event_buffer_size,
961
+ max_ack_batch_size=max_ack_batch_size,
962
+ max_ack_delay=max_ack_delay,
963
+ stopping_grace=stopping_grace,
964
+ timeout=timeout,
965
+ metadata=self._call_metadata,
966
+ credentials=credentials or self._call_credentials,
967
+ )
968
+
969
+ @retrygrpc
970
+ @autoreconnect
971
+ async def read_subscription_to_stream(
972
+ self,
973
+ group_name: str,
974
+ stream_name: str,
975
+ *,
976
+ event_buffer_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_EVENT_BUFFER_SIZE,
977
+ max_ack_batch_size: int = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_ACK_BATCH_SIZE,
978
+ max_ack_delay: float = DEFAULT_PERSISTENT_SUBSCRIPTION_MAX_ACK_DELAY,
979
+ stopping_grace: float = DEFAULT_PERSISTENT_SUBSCRIPTION_STOPPING_GRACE,
980
+ timeout: Optional[float] = None,
981
+ credentials: Optional[grpc.CallCredentials] = None,
982
+ ) -> AbstractAsyncPersistentSubscription:
983
+ """
984
+ Reads a persistent subscription on one stream.
985
+ """
986
+ return await self._connection.persistent_subscriptions.read(
987
+ group_name=group_name,
988
+ stream_name=stream_name,
989
+ event_buffer_size=event_buffer_size,
990
+ max_ack_batch_size=max_ack_batch_size,
991
+ max_ack_delay=max_ack_delay,
992
+ stopping_grace=stopping_grace,
993
+ timeout=timeout,
994
+ metadata=self._call_metadata,
995
+ credentials=credentials or self._call_credentials,
996
+ )
997
+
998
+ @retrygrpc
999
+ @autoreconnect
1000
+ async def get_subscription_info(
1001
+ self,
1002
+ group_name: str,
1003
+ stream_name: Optional[str] = None,
1004
+ *,
1005
+ timeout: Optional[float] = None,
1006
+ credentials: Optional[grpc.CallCredentials] = None,
1007
+ ) -> SubscriptionInfo:
1008
+ """
1009
+ Gets info for a persistent subscription.
1010
+ """
1011
+ return await self._connection.persistent_subscriptions.get_info(
1012
+ group_name=group_name,
1013
+ stream_name=stream_name,
1014
+ timeout=timeout,
1015
+ metadata=self._call_metadata,
1016
+ credentials=credentials or self._call_credentials,
1017
+ )
1018
+
1019
+ @retrygrpc
1020
+ @autoreconnect
1021
+ async def list_subscriptions(
1022
+ self,
1023
+ *,
1024
+ timeout: Optional[float] = None,
1025
+ credentials: Optional[grpc.CallCredentials] = None,
1026
+ ) -> Sequence[SubscriptionInfo]:
1027
+ """
1028
+ Lists all persistent subscriptions.
1029
+ """
1030
+ return await self._connection.persistent_subscriptions.list(
1031
+ timeout=timeout,
1032
+ metadata=self._call_metadata,
1033
+ credentials=credentials or self._call_credentials,
1034
+ )
1035
+
1036
+ @retrygrpc
1037
+ @autoreconnect
1038
+ async def list_subscriptions_to_stream(
1039
+ self,
1040
+ stream_name: str,
1041
+ *,
1042
+ timeout: Optional[float] = None,
1043
+ credentials: Optional[grpc.CallCredentials] = None,
1044
+ ) -> Sequence[SubscriptionInfo]:
1045
+ """
1046
+ Lists persistent stream subscriptions.
1047
+ """
1048
+ return await self._connection.persistent_subscriptions.list(
1049
+ stream_name=stream_name,
1050
+ timeout=timeout,
1051
+ metadata=self._call_metadata,
1052
+ credentials=credentials or self._call_credentials,
1053
+ )
1054
+
1055
+ @overload
1056
+ async def update_subscription_to_stream(
1057
+ self,
1058
+ group_name: str,
1059
+ stream_name: str,
1060
+ *,
1061
+ resolve_links: Optional[bool] = None,
1062
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1063
+ message_timeout: Optional[float] = None,
1064
+ max_retry_count: Optional[int] = None,
1065
+ min_checkpoint_count: Optional[int] = None,
1066
+ max_checkpoint_count: Optional[int] = None,
1067
+ checkpoint_after: Optional[float] = None,
1068
+ max_subscriber_count: Optional[int] = None,
1069
+ live_buffer_size: Optional[int] = None,
1070
+ read_batch_size: Optional[int] = None,
1071
+ history_buffer_size: Optional[int] = None,
1072
+ extra_statistics: Optional[bool] = None,
1073
+ timeout: Optional[float] = None,
1074
+ credentials: Optional[grpc.CallCredentials] = None,
1075
+ ) -> None:
1076
+ """
1077
+ Signature for updating subscription to run from same stream position.
1078
+ """
1079
+
1080
+ @overload
1081
+ async def update_subscription_to_stream(
1082
+ self,
1083
+ group_name: str,
1084
+ stream_name: str,
1085
+ *,
1086
+ from_end: Literal[False],
1087
+ resolve_links: Optional[bool] = None,
1088
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1089
+ message_timeout: Optional[float] = None,
1090
+ max_retry_count: Optional[int] = None,
1091
+ min_checkpoint_count: Optional[int] = None,
1092
+ max_checkpoint_count: Optional[int] = None,
1093
+ checkpoint_after: Optional[float] = None,
1094
+ max_subscriber_count: Optional[int] = None,
1095
+ live_buffer_size: Optional[int] = None,
1096
+ read_batch_size: Optional[int] = None,
1097
+ history_buffer_size: Optional[int] = None,
1098
+ extra_statistics: Optional[bool] = None,
1099
+ timeout: Optional[float] = None,
1100
+ credentials: Optional[grpc.CallCredentials] = None,
1101
+ ) -> None:
1102
+ """
1103
+ Signature for updating subscription to run from start of stream.
1104
+ """
1105
+
1106
+ @overload
1107
+ async def update_subscription_to_stream(
1108
+ self,
1109
+ group_name: str,
1110
+ stream_name: str,
1111
+ *,
1112
+ from_end: Literal[True],
1113
+ resolve_links: Optional[bool] = None,
1114
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1115
+ message_timeout: Optional[float] = None,
1116
+ max_retry_count: Optional[int] = None,
1117
+ min_checkpoint_count: Optional[int] = None,
1118
+ max_checkpoint_count: Optional[int] = None,
1119
+ checkpoint_after: Optional[float] = None,
1120
+ max_subscriber_count: Optional[int] = None,
1121
+ live_buffer_size: Optional[int] = None,
1122
+ read_batch_size: Optional[int] = None,
1123
+ history_buffer_size: Optional[int] = None,
1124
+ extra_statistics: Optional[bool] = None,
1125
+ timeout: Optional[float] = None,
1126
+ credentials: Optional[grpc.CallCredentials] = None,
1127
+ ) -> None:
1128
+ """
1129
+ Signature for updating subscription to run from end of stream.
1130
+ """
1131
+
1132
+ @overload
1133
+ async def update_subscription_to_stream(
1134
+ self,
1135
+ group_name: str,
1136
+ stream_name: str,
1137
+ *,
1138
+ stream_position: int,
1139
+ resolve_links: Optional[bool] = None,
1140
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1141
+ message_timeout: Optional[float] = None,
1142
+ max_retry_count: Optional[int] = None,
1143
+ min_checkpoint_count: Optional[int] = None,
1144
+ max_checkpoint_count: Optional[int] = None,
1145
+ checkpoint_after: Optional[float] = None,
1146
+ max_subscriber_count: Optional[int] = None,
1147
+ live_buffer_size: Optional[int] = None,
1148
+ read_batch_size: Optional[int] = None,
1149
+ history_buffer_size: Optional[int] = None,
1150
+ extra_statistics: Optional[bool] = None,
1151
+ timeout: Optional[float] = None,
1152
+ credentials: Optional[grpc.CallCredentials] = None,
1153
+ ) -> None:
1154
+ """
1155
+ Signature for updating subscription to run from stream position.
1156
+ """
1157
+
1158
+ @retrygrpc
1159
+ @autoreconnect
1160
+ async def update_subscription_to_stream(
1161
+ self,
1162
+ group_name: str,
1163
+ stream_name: str,
1164
+ *,
1165
+ from_end: Optional[bool] = None,
1166
+ stream_position: Optional[int] = None,
1167
+ resolve_links: Optional[bool] = None,
1168
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1169
+ message_timeout: Optional[float] = None,
1170
+ max_retry_count: Optional[int] = None,
1171
+ min_checkpoint_count: Optional[int] = None,
1172
+ max_checkpoint_count: Optional[int] = None,
1173
+ checkpoint_after: Optional[float] = None,
1174
+ max_subscriber_count: Optional[int] = None,
1175
+ live_buffer_size: Optional[int] = None,
1176
+ read_batch_size: Optional[int] = None,
1177
+ history_buffer_size: Optional[int] = None,
1178
+ extra_statistics: Optional[bool] = None,
1179
+ timeout: Optional[float] = None,
1180
+ credentials: Optional[grpc.CallCredentials] = None,
1181
+ ) -> None:
1182
+ """
1183
+ Updates a persistent subscription on one stream.
1184
+ """
1185
+
1186
+ info = await self.get_subscription_info(
1187
+ group_name=group_name,
1188
+ stream_name=stream_name,
1189
+ timeout=timeout,
1190
+ credentials=credentials,
1191
+ )
1192
+ kwargs = info.update_stream_kwargs(
1193
+ from_end=from_end,
1194
+ stream_position=stream_position,
1195
+ resolve_links=resolve_links,
1196
+ consumer_strategy=consumer_strategy,
1197
+ message_timeout=message_timeout,
1198
+ max_retry_count=max_retry_count,
1199
+ min_checkpoint_count=min_checkpoint_count,
1200
+ max_checkpoint_count=max_checkpoint_count,
1201
+ checkpoint_after=checkpoint_after,
1202
+ max_subscriber_count=max_subscriber_count,
1203
+ live_buffer_size=live_buffer_size,
1204
+ read_batch_size=read_batch_size,
1205
+ history_buffer_size=history_buffer_size,
1206
+ extra_statistics=extra_statistics,
1207
+ )
1208
+
1209
+ await self._connection.persistent_subscriptions.update(
1210
+ group_name=group_name,
1211
+ stream_name=stream_name,
1212
+ **kwargs,
1213
+ timeout=timeout if timeout is not None else self._default_deadline,
1214
+ metadata=self._call_metadata,
1215
+ credentials=credentials or self._call_credentials,
1216
+ )
1217
+
1218
+ @overload
1219
+ async def update_subscription_to_all(
1220
+ self,
1221
+ group_name: str,
1222
+ *,
1223
+ resolve_links: Optional[bool] = None,
1224
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1225
+ message_timeout: Optional[float] = None,
1226
+ max_retry_count: Optional[int] = None,
1227
+ min_checkpoint_count: Optional[int] = None,
1228
+ max_checkpoint_count: Optional[int] = None,
1229
+ checkpoint_after: Optional[float] = None,
1230
+ max_subscriber_count: Optional[int] = None,
1231
+ live_buffer_size: Optional[int] = None,
1232
+ read_batch_size: Optional[int] = None,
1233
+ history_buffer_size: Optional[int] = None,
1234
+ extra_statistics: Optional[bool] = None,
1235
+ timeout: Optional[float] = None,
1236
+ credentials: Optional[grpc.CallCredentials] = None,
1237
+ ) -> None:
1238
+ """
1239
+ Signature for updating subscription to run from same database position.
1240
+ """
1241
+
1242
+ @overload
1243
+ async def update_subscription_to_all(
1244
+ self,
1245
+ group_name: str,
1246
+ *,
1247
+ from_end: Literal[False],
1248
+ resolve_links: Optional[bool] = None,
1249
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1250
+ message_timeout: Optional[float] = None,
1251
+ max_retry_count: Optional[int] = None,
1252
+ min_checkpoint_count: Optional[int] = None,
1253
+ max_checkpoint_count: Optional[int] = None,
1254
+ checkpoint_after: Optional[float] = None,
1255
+ max_subscriber_count: Optional[int] = None,
1256
+ live_buffer_size: Optional[int] = None,
1257
+ read_batch_size: Optional[int] = None,
1258
+ history_buffer_size: Optional[int] = None,
1259
+ extra_statistics: Optional[bool] = None,
1260
+ timeout: Optional[float] = None,
1261
+ credentials: Optional[grpc.CallCredentials] = None,
1262
+ ) -> None:
1263
+ """
1264
+ Signature for updating subscription to run from start of database.
1265
+ """
1266
+
1267
+ @overload
1268
+ async def update_subscription_to_all(
1269
+ self,
1270
+ group_name: str,
1271
+ *,
1272
+ from_end: Literal[True],
1273
+ resolve_links: Optional[bool] = None,
1274
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1275
+ message_timeout: Optional[float] = None,
1276
+ max_retry_count: Optional[int] = None,
1277
+ min_checkpoint_count: Optional[int] = None,
1278
+ max_checkpoint_count: Optional[int] = None,
1279
+ checkpoint_after: Optional[float] = None,
1280
+ max_subscriber_count: Optional[int] = None,
1281
+ live_buffer_size: Optional[int] = None,
1282
+ read_batch_size: Optional[int] = None,
1283
+ history_buffer_size: Optional[int] = None,
1284
+ extra_statistics: Optional[bool] = None,
1285
+ timeout: Optional[float] = None,
1286
+ credentials: Optional[grpc.CallCredentials] = None,
1287
+ ) -> None:
1288
+ """
1289
+ Signature for updating subscription to run from end of database.
1290
+ """
1291
+
1292
+ @overload
1293
+ async def update_subscription_to_all(
1294
+ self,
1295
+ group_name: str,
1296
+ *,
1297
+ commit_position: int,
1298
+ resolve_links: Optional[bool] = None,
1299
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1300
+ message_timeout: Optional[float] = None,
1301
+ max_retry_count: Optional[int] = None,
1302
+ min_checkpoint_count: Optional[int] = None,
1303
+ max_checkpoint_count: Optional[int] = None,
1304
+ checkpoint_after: Optional[float] = None,
1305
+ max_subscriber_count: Optional[int] = None,
1306
+ live_buffer_size: Optional[int] = None,
1307
+ read_batch_size: Optional[int] = None,
1308
+ history_buffer_size: Optional[int] = None,
1309
+ extra_statistics: Optional[bool] = None,
1310
+ timeout: Optional[float] = None,
1311
+ credentials: Optional[grpc.CallCredentials] = None,
1312
+ ) -> None:
1313
+ """
1314
+ Signature for updating persistent subscription to run from a commit position.
1315
+ """
1316
+
1317
+ @retrygrpc
1318
+ @autoreconnect
1319
+ async def update_subscription_to_all(
1320
+ self,
1321
+ group_name: str,
1322
+ *,
1323
+ from_end: Optional[bool] = None,
1324
+ commit_position: Optional[int] = None,
1325
+ resolve_links: Optional[bool] = None,
1326
+ consumer_strategy: Optional[ConsumerStrategy] = None,
1327
+ message_timeout: Optional[float] = None,
1328
+ max_retry_count: Optional[int] = None,
1329
+ min_checkpoint_count: Optional[int] = None,
1330
+ max_checkpoint_count: Optional[int] = None,
1331
+ checkpoint_after: Optional[float] = None,
1332
+ max_subscriber_count: Optional[int] = None,
1333
+ live_buffer_size: Optional[int] = None,
1334
+ read_batch_size: Optional[int] = None,
1335
+ history_buffer_size: Optional[int] = None,
1336
+ extra_statistics: Optional[bool] = None,
1337
+ timeout: Optional[float] = None,
1338
+ credentials: Optional[grpc.CallCredentials] = None,
1339
+ ) -> None:
1340
+ """
1341
+ Updates a persistent subscription on all streams.
1342
+ """
1343
+
1344
+ info = await self.get_subscription_info(
1345
+ group_name=group_name, timeout=timeout, credentials=credentials
1346
+ )
1347
+ kwargs = info.update_all_kwargs(
1348
+ from_end=from_end,
1349
+ commit_position=commit_position,
1350
+ resolve_links=resolve_links,
1351
+ consumer_strategy=consumer_strategy,
1352
+ message_timeout=message_timeout,
1353
+ max_retry_count=max_retry_count,
1354
+ min_checkpoint_count=min_checkpoint_count,
1355
+ max_checkpoint_count=max_checkpoint_count,
1356
+ checkpoint_after=checkpoint_after,
1357
+ max_subscriber_count=max_subscriber_count,
1358
+ live_buffer_size=live_buffer_size,
1359
+ read_batch_size=read_batch_size,
1360
+ history_buffer_size=history_buffer_size,
1361
+ extra_statistics=extra_statistics,
1362
+ )
1363
+
1364
+ await self._connection.persistent_subscriptions.update(
1365
+ group_name=group_name,
1366
+ **kwargs,
1367
+ timeout=timeout if timeout is not None else self._default_deadline,
1368
+ metadata=self._call_metadata,
1369
+ credentials=credentials or self._call_credentials,
1370
+ )
1371
+
1372
+ @retrygrpc
1373
+ @autoreconnect
1374
+ async def replay_parked_events(
1375
+ self,
1376
+ group_name: str,
1377
+ stream_name: Optional[str] = None,
1378
+ *,
1379
+ timeout: Optional[float] = None,
1380
+ credentials: Optional[grpc.CallCredentials] = None,
1381
+ ) -> None:
1382
+ timeout = timeout if timeout is not None else self._default_deadline
1383
+
1384
+ await self._connection.persistent_subscriptions.replay_parked(
1385
+ group_name=group_name,
1386
+ stream_name=stream_name,
1387
+ timeout=timeout,
1388
+ metadata=self._call_metadata,
1389
+ credentials=credentials or self._call_credentials,
1390
+ )
1391
+
1392
+ @retrygrpc
1393
+ @autoreconnect
1394
+ async def delete_subscription(
1395
+ self,
1396
+ group_name: str,
1397
+ stream_name: Optional[str] = None,
1398
+ *,
1399
+ timeout: Optional[float] = None,
1400
+ credentials: Optional[grpc.CallCredentials] = None,
1401
+ ) -> None:
1402
+ """
1403
+ Deletes a persistent subscription.
1404
+ """
1405
+ timeout = timeout if timeout is not None else self._default_deadline
1406
+
1407
+ await self._connection.persistent_subscriptions.delete(
1408
+ group_name=group_name,
1409
+ stream_name=stream_name,
1410
+ timeout=timeout,
1411
+ metadata=self._call_metadata,
1412
+ credentials=credentials or self._call_credentials,
1413
+ )
1414
+
1415
+ @retrygrpc
1416
+ @autoreconnect
1417
+ async def create_projection(
1418
+ self,
1419
+ *,
1420
+ name: str,
1421
+ query: str,
1422
+ emit_enabled: bool = False,
1423
+ track_emitted_streams: bool = False,
1424
+ timeout: Optional[float] = None,
1425
+ credentials: Optional[grpc.CallCredentials] = None,
1426
+ ) -> None:
1427
+ """
1428
+ Creates a projection.
1429
+ """
1430
+ timeout = timeout if timeout is not None else self._default_deadline
1431
+
1432
+ await self._connection.projections.create(
1433
+ query=query,
1434
+ name=name,
1435
+ emit_enabled=emit_enabled,
1436
+ track_emitted_streams=track_emitted_streams,
1437
+ timeout=timeout,
1438
+ metadata=self._call_metadata,
1439
+ credentials=credentials or self._call_credentials,
1440
+ )
1441
+
1442
+ @retrygrpc
1443
+ @autoreconnect
1444
+ async def update_projection(
1445
+ self,
1446
+ name: str,
1447
+ *,
1448
+ query: str,
1449
+ emit_enabled: bool = False,
1450
+ timeout: Optional[float] = None,
1451
+ credentials: Optional[grpc.CallCredentials] = None,
1452
+ ) -> None:
1453
+ """
1454
+ Updates a projection.
1455
+ """
1456
+ timeout = timeout if timeout is not None else self._default_deadline
1457
+
1458
+ await self._connection.projections.update(
1459
+ name=name,
1460
+ query=query,
1461
+ emit_enabled=emit_enabled,
1462
+ timeout=timeout,
1463
+ metadata=self._call_metadata,
1464
+ credentials=credentials or self._call_credentials,
1465
+ )
1466
+
1467
+ @retrygrpc
1468
+ @autoreconnect
1469
+ async def delete_projection(
1470
+ self,
1471
+ name: str,
1472
+ *,
1473
+ delete_emitted_streams: bool = False,
1474
+ delete_state_stream: bool = False,
1475
+ delete_checkpoint_stream: bool = False,
1476
+ timeout: Optional[float] = None,
1477
+ credentials: Optional[grpc.CallCredentials] = None,
1478
+ ) -> None:
1479
+ """
1480
+ Deletes a projection.
1481
+ """
1482
+ timeout = timeout if timeout is not None else self._default_deadline
1483
+
1484
+ await self._connection.projections.delete(
1485
+ name=name,
1486
+ delete_emitted_streams=delete_emitted_streams,
1487
+ delete_state_stream=delete_state_stream,
1488
+ delete_checkpoint_stream=delete_checkpoint_stream,
1489
+ timeout=timeout,
1490
+ metadata=self._call_metadata,
1491
+ credentials=credentials or self._call_credentials,
1492
+ )
1493
+
1494
+ @retrygrpc
1495
+ @autoreconnect
1496
+ async def get_projection_statistics(
1497
+ self,
1498
+ *,
1499
+ name: str,
1500
+ timeout: Optional[float] = None,
1501
+ credentials: Optional[grpc.CallCredentials] = None,
1502
+ ) -> ProjectionStatistics:
1503
+ """
1504
+ Gets projection statistics.
1505
+ """
1506
+ timeout = timeout if timeout is not None else self._default_deadline
1507
+
1508
+ return await self._connection.projections.get_statistics(
1509
+ name=name,
1510
+ timeout=timeout,
1511
+ metadata=self._call_metadata,
1512
+ credentials=credentials or self._call_credentials,
1513
+ )
1514
+
1515
+ @retrygrpc
1516
+ @autoreconnect
1517
+ async def disable_projection(
1518
+ self,
1519
+ name: str,
1520
+ *,
1521
+ timeout: Optional[float] = None,
1522
+ credentials: Optional[grpc.CallCredentials] = None,
1523
+ ) -> None:
1524
+ """
1525
+ Disables a projection.
1526
+ """
1527
+ timeout = timeout if timeout is not None else self._default_deadline
1528
+
1529
+ await self._connection.projections.disable(
1530
+ name=name,
1531
+ write_checkpoint=True,
1532
+ timeout=timeout,
1533
+ metadata=self._call_metadata,
1534
+ credentials=credentials or self._call_credentials,
1535
+ )
1536
+
1537
+ @retrygrpc
1538
+ @autoreconnect
1539
+ async def enable_projection(
1540
+ self,
1541
+ name: str,
1542
+ *,
1543
+ timeout: Optional[float] = None,
1544
+ credentials: Optional[grpc.CallCredentials] = None,
1545
+ ) -> None:
1546
+ """
1547
+ Disables a projection.
1548
+ """
1549
+ timeout = timeout if timeout is not None else self._default_deadline
1550
+
1551
+ await self._connection.projections.enable(
1552
+ name=name,
1553
+ timeout=timeout,
1554
+ metadata=self._call_metadata,
1555
+ credentials=credentials or self._call_credentials,
1556
+ )
1557
+
1558
+ @retrygrpc
1559
+ @autoreconnect
1560
+ async def reset_projection(
1561
+ self,
1562
+ name: str,
1563
+ *,
1564
+ timeout: Optional[float] = None,
1565
+ credentials: Optional[grpc.CallCredentials] = None,
1566
+ ) -> None:
1567
+ """
1568
+ Resets a projection.
1569
+ """
1570
+ timeout = timeout if timeout is not None else self._default_deadline
1571
+
1572
+ await self._connection.projections.reset(
1573
+ name=name,
1574
+ write_checkpoint=True,
1575
+ timeout=timeout,
1576
+ metadata=self._call_metadata,
1577
+ credentials=credentials or self._call_credentials,
1578
+ )
1579
+
1580
+ @retrygrpc
1581
+ @autoreconnect
1582
+ async def get_projection_state(
1583
+ self,
1584
+ name: str,
1585
+ *,
1586
+ timeout: Optional[float] = None,
1587
+ credentials: Optional[grpc.CallCredentials] = None,
1588
+ ) -> ProjectionState:
1589
+ """
1590
+ Gets projection state.
1591
+ """
1592
+ timeout = timeout if timeout is not None else self._default_deadline
1593
+
1594
+ return await self._connection.projections.get_state(
1595
+ name=name,
1596
+ partition="",
1597
+ timeout=timeout,
1598
+ metadata=self._call_metadata,
1599
+ credentials=credentials or self._call_credentials,
1600
+ )
1601
+
1602
+ # @retrygrpc
1603
+ # @autoreconnect
1604
+ # async def get_projection_result(
1605
+ # self,
1606
+ # name: str,
1607
+ # *,
1608
+ # timeout: Optional[float] = None,
1609
+ # credentials: Optional[grpc.CallCredentials] = None,
1610
+ # ) -> ProjectionResult:
1611
+ # """
1612
+ # Gets projection result.
1613
+ # """
1614
+ # timeout = timeout if timeout is not None else self._default_deadline
1615
+ #
1616
+ # return await self._connection.projections.get_result(
1617
+ # name=name,
1618
+ # partition="",
1619
+ # timeout=timeout,
1620
+ # metadata=self._call_metadata,
1621
+ # credentials=credentials or self._call_credentials,
1622
+ # )
1623
+
1624
+ @retrygrpc
1625
+ @autoreconnect
1626
+ async def restart_projections_subsystem(
1627
+ self,
1628
+ *,
1629
+ timeout: Optional[float] = None,
1630
+ credentials: Optional[grpc.CallCredentials] = None,
1631
+ ) -> None:
1632
+ """
1633
+ Restarts projections subsystem.
1634
+ """
1635
+ timeout = timeout if timeout is not None else self._default_deadline
1636
+
1637
+ return await self._connection.projections.restart_subsystem(
1638
+ timeout=timeout,
1639
+ metadata=self._call_metadata,
1640
+ credentials=credentials or self._call_credentials,
1641
+ )
1642
+
1643
+ async def close(self) -> None:
1644
+ if not self._is_closed:
1645
+ try:
1646
+ esdb_connection = self._connection
1647
+ del self._connection
1648
+ except AttributeError: # pragma: no cover
1649
+ pass
1650
+ else:
1651
+ await esdb_connection.close()
1652
+ self._is_closed = True
1653
+
1654
+ async def __aenter__(self) -> AsyncKurrentDBClient:
1655
+ return self
1656
+
1657
+ async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
1658
+ await self.close()
1659
+
1660
+
1661
+ class _AsyncioKurrentDBClient(AsyncKurrentDBClient):
1662
+ pass