eventsourcing 9.4.0a7__py3-none-any.whl → 9.4.0b1__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.
Potentially problematic release.
This version of eventsourcing might be problematic. Click here for more details.
- eventsourcing/application.py +22 -30
- eventsourcing/cipher.py +3 -1
- eventsourcing/dispatch.py +52 -11
- eventsourcing/domain.py +373 -360
- eventsourcing/interface.py +1 -1
- eventsourcing/persistence.py +26 -28
- eventsourcing/popo.py +5 -1
- eventsourcing/postgres.py +174 -127
- eventsourcing/projection.py +82 -26
- eventsourcing/sqlite.py +5 -1
- eventsourcing/system.py +14 -9
- eventsourcing/tests/application.py +57 -49
- eventsourcing/tests/domain.py +8 -6
- eventsourcing/tests/persistence.py +170 -143
- eventsourcing/tests/postgres_utils.py +12 -9
- eventsourcing/utils.py +27 -17
- {eventsourcing-9.4.0a7.dist-info → eventsourcing-9.4.0b1.dist-info}/METADATA +2 -2
- eventsourcing-9.4.0b1.dist-info/RECORD +26 -0
- eventsourcing-9.4.0a7.dist-info/RECORD +0 -26
- {eventsourcing-9.4.0a7.dist-info → eventsourcing-9.4.0b1.dist-info}/AUTHORS +0 -0
- {eventsourcing-9.4.0a7.dist-info → eventsourcing-9.4.0b1.dist-info}/LICENSE +0 -0
- {eventsourcing-9.4.0a7.dist-info → eventsourcing-9.4.0b1.dist-info}/WHEEL +0 -0
eventsourcing/interface.py
CHANGED
eventsourcing/persistence.py
CHANGED
|
@@ -12,9 +12,10 @@ from queue import Queue
|
|
|
12
12
|
from threading import Condition, Event, Lock, Semaphore, Thread, Timer
|
|
13
13
|
from time import monotonic, sleep, time
|
|
14
14
|
from types import GenericAlias, ModuleType
|
|
15
|
-
from typing import TYPE_CHECKING, Any, Generic,
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Generic, Union, cast
|
|
16
16
|
from uuid import UUID
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
from typing_extensions import TypeVar
|
|
18
19
|
|
|
19
20
|
from eventsourcing.domain import DomainEventProtocol, EventSourcingError
|
|
20
21
|
from eventsourcing.utils import (
|
|
@@ -284,15 +285,6 @@ class Mapper:
|
|
|
284
285
|
state=stored_state,
|
|
285
286
|
)
|
|
286
287
|
|
|
287
|
-
def from_domain_event(self, domain_event: DomainEventProtocol) -> StoredEvent:
|
|
288
|
-
warn(
|
|
289
|
-
"'from_domain_event()' is deprecated, use 'to_stored_event()' instead",
|
|
290
|
-
DeprecationWarning,
|
|
291
|
-
stacklevel=2,
|
|
292
|
-
)
|
|
293
|
-
|
|
294
|
-
return self.to_stored_event(domain_event)
|
|
295
|
-
|
|
296
288
|
def to_domain_event(self, stored_event: StoredEvent) -> DomainEventProtocol:
|
|
297
289
|
"""
|
|
298
290
|
Converts the given :class:`StoredEvent` to a domain event object.
|
|
@@ -508,24 +500,27 @@ class TrackingRecorder(Recorder, ABC):
|
|
|
508
500
|
"""
|
|
509
501
|
|
|
510
502
|
@abstractmethod
|
|
511
|
-
def has_tracking_id(
|
|
503
|
+
def has_tracking_id(
|
|
504
|
+
self, application_name: str, notification_id: int | None
|
|
505
|
+
) -> bool:
|
|
512
506
|
"""
|
|
513
507
|
Returns True if a tracking object with the given application name
|
|
514
|
-
and notification ID has been recorded,
|
|
508
|
+
and notification ID has been recorded, and True if given notification_id is
|
|
509
|
+
None, otherwise returns False.
|
|
515
510
|
"""
|
|
516
511
|
|
|
517
512
|
def wait(
|
|
518
513
|
self,
|
|
519
514
|
application_name: str,
|
|
520
|
-
notification_id: int,
|
|
515
|
+
notification_id: int | None,
|
|
521
516
|
timeout: float = 1.0,
|
|
522
517
|
interrupt: Event | None = None,
|
|
523
518
|
) -> None:
|
|
524
519
|
"""
|
|
525
|
-
Block until a tracking object with the given application name and
|
|
526
|
-
notification ID has been recorded.
|
|
520
|
+
Block until a tracking object with the given application name and a
|
|
521
|
+
notification ID greater than equal to the given value has been recorded.
|
|
527
522
|
|
|
528
|
-
Polls
|
|
523
|
+
Polls max_tracking_id() with exponential backoff until the timeout
|
|
529
524
|
is reached, or until the optional interrupt event is set.
|
|
530
525
|
|
|
531
526
|
The timeout argument should be a floating point number specifying a
|
|
@@ -539,7 +534,10 @@ class TrackingRecorder(Recorder, ABC):
|
|
|
539
534
|
deadline = monotonic() + timeout
|
|
540
535
|
delay_ms = 1.0
|
|
541
536
|
while True:
|
|
542
|
-
|
|
537
|
+
max_tracking_id = self.max_tracking_id(application_name)
|
|
538
|
+
if notification_id is None or (
|
|
539
|
+
max_tracking_id is not None and max_tracking_id >= notification_id
|
|
540
|
+
):
|
|
543
541
|
break
|
|
544
542
|
if interrupt:
|
|
545
543
|
if interrupt.wait(timeout=delay_ms / 1000):
|
|
@@ -634,12 +632,10 @@ class EventStore:
|
|
|
634
632
|
)
|
|
635
633
|
|
|
636
634
|
|
|
637
|
-
|
|
638
|
-
"
|
|
635
|
+
TTrackingRecorder = TypeVar(
|
|
636
|
+
"TTrackingRecorder", bound=TrackingRecorder, default=TrackingRecorder
|
|
639
637
|
)
|
|
640
638
|
|
|
641
|
-
TTrackingRecorder = TypeVar("TTrackingRecorder", bound=TrackingRecorder)
|
|
642
|
-
|
|
643
639
|
|
|
644
640
|
class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
|
|
645
641
|
"""
|
|
@@ -658,14 +654,15 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
|
|
|
658
654
|
|
|
659
655
|
@classmethod
|
|
660
656
|
def construct(
|
|
661
|
-
cls: type[
|
|
662
|
-
|
|
657
|
+
cls: type[InfrastructureFactory[TTrackingRecorder]],
|
|
658
|
+
env: Environment | None = None,
|
|
659
|
+
) -> InfrastructureFactory[TTrackingRecorder]:
|
|
663
660
|
"""
|
|
664
661
|
Constructs concrete infrastructure factory for given
|
|
665
662
|
named application. Reads and resolves persistence
|
|
666
663
|
topic from environment variable 'PERSISTENCE_MODULE'.
|
|
667
664
|
"""
|
|
668
|
-
factory_cls: type[InfrastructureFactory[
|
|
665
|
+
factory_cls: type[InfrastructureFactory[TTrackingRecorder]]
|
|
669
666
|
if env is None:
|
|
670
667
|
env = Environment()
|
|
671
668
|
topic = (
|
|
@@ -684,7 +681,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
|
|
|
684
681
|
or "eventsourcing.popo"
|
|
685
682
|
)
|
|
686
683
|
try:
|
|
687
|
-
obj: type[InfrastructureFactory[
|
|
684
|
+
obj: type[InfrastructureFactory[TTrackingRecorder]] | ModuleType = (
|
|
688
685
|
resolve_topic(topic)
|
|
689
686
|
)
|
|
690
687
|
except TopicError as e:
|
|
@@ -697,7 +694,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
|
|
|
697
694
|
|
|
698
695
|
if isinstance(obj, ModuleType):
|
|
699
696
|
# Find the factory in the module.
|
|
700
|
-
factory_classes: list[type[InfrastructureFactory[
|
|
697
|
+
factory_classes: list[type[InfrastructureFactory[TTrackingRecorder]]] = []
|
|
701
698
|
for member in obj.__dict__.values():
|
|
702
699
|
if (
|
|
703
700
|
member is not InfrastructureFactory
|
|
@@ -724,7 +721,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
|
|
|
724
721
|
else:
|
|
725
722
|
msg = f"Not an infrastructure factory class or module: {topic}"
|
|
726
723
|
raise AssertionError(msg)
|
|
727
|
-
return
|
|
724
|
+
return factory_cls(env=env)
|
|
728
725
|
|
|
729
726
|
def __init__(self, env: Environment):
|
|
730
727
|
"""
|
|
@@ -757,6 +754,7 @@ class InfrastructureFactory(ABC, Generic[TTrackingRecorder]):
|
|
|
757
754
|
mapper_topic = self.env.get(self.MAPPER_TOPIC)
|
|
758
755
|
mapper_class = resolve_topic(mapper_topic) if mapper_topic else Mapper
|
|
759
756
|
|
|
757
|
+
assert isinstance(mapper_class, type) and issubclass(mapper_class, Mapper)
|
|
760
758
|
return mapper_class(
|
|
761
759
|
transcoder=transcoder or self.transcoder(),
|
|
762
760
|
cipher=self.cipher(),
|
eventsourcing/popo.py
CHANGED
|
@@ -219,7 +219,11 @@ class POPOTrackingRecorder(POPORecorder, TrackingRecorder):
|
|
|
219
219
|
with self._database_lock:
|
|
220
220
|
return self._max_tracking_ids[application_name]
|
|
221
221
|
|
|
222
|
-
def has_tracking_id(
|
|
222
|
+
def has_tracking_id(
|
|
223
|
+
self, application_name: str, notification_id: int | None
|
|
224
|
+
) -> bool:
|
|
225
|
+
if notification_id is None:
|
|
226
|
+
return True
|
|
223
227
|
with self._database_lock:
|
|
224
228
|
return notification_id in self._tracking_table[application_name]
|
|
225
229
|
|