flowevent 1.2__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.
- eventflow/__init__.py +123 -0
- eventflow/_callbacks.py +22 -0
- eventflow/_lifecycle.py +31 -0
- eventflow/actions.py +53 -0
- eventflow/async_event_bus.py +640 -0
- eventflow/base.py +180 -0
- eventflow/callback.py +318 -0
- eventflow/compatibility.py +14 -0
- eventflow/context.py +103 -0
- eventflow/contracts.py +40 -0
- eventflow/engine.py +466 -0
- eventflow/errors.py +21 -0
- eventflow/event_bus.py +594 -0
- eventflow/filtering.py +57 -0
- eventflow/history.py +111 -0
- eventflow/observability.py +133 -0
- eventflow/pipeline/__init__.py +7 -0
- eventflow/pipeline/async_.py +129 -0
- eventflow/pipeline/base.py +203 -0
- eventflow/pipeline/contracts.py +24 -0
- eventflow/pipeline/registry.py +95 -0
- eventflow/pipeline/sync.py +92 -0
- eventflow/py.typed +0 -0
- eventflow/scopes.py +185 -0
- eventflow/stream.py +241 -0
- eventflow/subscription.py +116 -0
- flowevent-1.2.dist-info/METADATA +1171 -0
- flowevent-1.2.dist-info/RECORD +31 -0
- flowevent-1.2.dist-info/WHEEL +5 -0
- flowevent-1.2.dist-info/licenses/LICENSE +21 -0
- flowevent-1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Subscription ownership for synchronous and asynchronous event buses."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import threading
|
|
7
|
+
from collections.abc import Awaitable, Callable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Subscription:
|
|
11
|
+
def __init__(self, subscription_id: int, cancel: Callable[[], None]) -> None:
|
|
12
|
+
self._id = subscription_id
|
|
13
|
+
self._cancel = cancel
|
|
14
|
+
self._active = True
|
|
15
|
+
self._lock = threading.Lock()
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def id(self) -> int:
|
|
19
|
+
return self._id
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def active(self) -> bool:
|
|
23
|
+
with self._lock:
|
|
24
|
+
return self._active
|
|
25
|
+
|
|
26
|
+
def _deactivate(self) -> bool:
|
|
27
|
+
with self._lock:
|
|
28
|
+
if not self._active:
|
|
29
|
+
return False
|
|
30
|
+
self._active = False
|
|
31
|
+
return True
|
|
32
|
+
|
|
33
|
+
def cancel(self) -> None:
|
|
34
|
+
self._consume()
|
|
35
|
+
|
|
36
|
+
def _consume(self) -> bool:
|
|
37
|
+
if not self._deactivate():
|
|
38
|
+
return False
|
|
39
|
+
try:
|
|
40
|
+
self._cancel()
|
|
41
|
+
except BaseException:
|
|
42
|
+
with self._lock:
|
|
43
|
+
self._active = True
|
|
44
|
+
raise
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
def __enter__(self) -> "Subscription":
|
|
48
|
+
return self
|
|
49
|
+
|
|
50
|
+
def __exit__(self, *_args: object) -> None:
|
|
51
|
+
self.cancel()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class AsyncSubscription:
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
subscription_id: int,
|
|
58
|
+
cancel: Callable[[], Awaitable[None]],
|
|
59
|
+
) -> None:
|
|
60
|
+
self._id = subscription_id
|
|
61
|
+
self._cancel = cancel
|
|
62
|
+
self._active = True
|
|
63
|
+
self._cancel_completion: asyncio.Future[BaseException | None] | None = None
|
|
64
|
+
self._cancel_owner: asyncio.Task | None = None
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def id(self) -> int:
|
|
68
|
+
return self._id
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def active(self) -> bool:
|
|
72
|
+
return self._active
|
|
73
|
+
|
|
74
|
+
def _deactivate(self) -> bool:
|
|
75
|
+
if not self._active:
|
|
76
|
+
return False
|
|
77
|
+
self._active = False
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
async def cancel(self) -> None:
|
|
81
|
+
await self._consume()
|
|
82
|
+
|
|
83
|
+
async def _consume(self) -> bool:
|
|
84
|
+
completion = self._cancel_completion
|
|
85
|
+
if not self._active:
|
|
86
|
+
if completion is None:
|
|
87
|
+
return False
|
|
88
|
+
if self._cancel_owner is asyncio.current_task():
|
|
89
|
+
return False
|
|
90
|
+
error = await asyncio.shield(completion)
|
|
91
|
+
if error is not None:
|
|
92
|
+
raise error
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
self._active = False
|
|
96
|
+
completion = asyncio.get_running_loop().create_future()
|
|
97
|
+
self._cancel_completion = completion
|
|
98
|
+
self._cancel_owner = asyncio.current_task()
|
|
99
|
+
try:
|
|
100
|
+
await self._cancel()
|
|
101
|
+
except BaseException as error:
|
|
102
|
+
self._active = True
|
|
103
|
+
self._cancel_completion = None
|
|
104
|
+
self._cancel_owner = None
|
|
105
|
+
completion.set_result(error)
|
|
106
|
+
raise
|
|
107
|
+
self._cancel_completion = None
|
|
108
|
+
self._cancel_owner = None
|
|
109
|
+
completion.set_result(None)
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
async def __aenter__(self) -> "AsyncSubscription":
|
|
113
|
+
return self
|
|
114
|
+
|
|
115
|
+
async def __aexit__(self, *_args: object) -> None:
|
|
116
|
+
await self.cancel()
|