python-event-sourcery 0.4.0a4__tar.gz → 0.4.0a6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/PKG-INFO +1 -1
  2. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/aggregate/repository.py +8 -2
  3. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/__init__.py +2 -2
  4. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/dispatcher.py +4 -4
  5. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/event/__init__.py +2 -2
  6. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/event/dto.py +7 -5
  7. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/event/serde.py +5 -5
  8. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/event_store.py +25 -19
  9. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/outbox.py +1 -1
  10. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/subscription.py +1 -1
  11. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/read_model/projector.py +12 -12
  12. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/outbox.py +3 -3
  13. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/subscription.py +9 -2
  14. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/cursors_dao.py +1 -1
  15. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/event_store.py +1 -1
  16. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/pyproject.toml +1 -1
  17. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/LICENSE +0 -0
  18. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/__init__.py +0 -0
  19. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/aggregate/__init__.py +0 -0
  20. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/aggregate/aggregate.py +0 -0
  21. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/event/registry.py +0 -0
  22. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/exceptions.py +0 -0
  23. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/factory.py +0 -0
  24. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/in_memory.py +0 -0
  25. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/interfaces.py +0 -0
  26. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/stream_id.py +0 -0
  27. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/event_store/versioning.py +0 -0
  28. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/py.typed +0 -0
  29. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/read_model/__init__.py +0 -0
  30. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery/read_model/cursors_dao.py +0 -0
  31. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/__init__.py +0 -0
  32. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/dto.py +0 -0
  33. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/event_store.py +0 -0
  34. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/py.typed +0 -0
  35. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_esdb/stream.py +0 -0
  36. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/__init__.py +0 -0
  37. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/dto.py +0 -0
  38. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/guid.py +0 -0
  39. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/jsonb.py +0 -0
  40. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/models.py +0 -0
  41. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/outbox.py +0 -0
  42. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/py.typed +0 -0
  43. {python_event_sourcery-0.4.0a4 → python_event_sourcery-0.4.0a6}/event_sourcery_sqlalchemy/subscription.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-event-sourcery
3
- Version: 0.4.0a4
3
+ Version: 0.4.0a6
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Your Name
@@ -3,7 +3,13 @@ from contextlib import contextmanager
3
3
  from typing import Generic, TypeVar, cast
4
4
 
5
5
  from event_sourcery.aggregate import Aggregate
6
- from event_sourcery.event_store import Event, EventStore, Metadata, StreamId, StreamUUID
6
+ from event_sourcery.event_store import (
7
+ Event,
8
+ EventStore,
9
+ StreamId,
10
+ StreamUUID,
11
+ WrappedEvent,
12
+ )
7
13
 
8
14
  TAggregate = TypeVar("TAggregate", bound=Aggregate)
9
15
  TEvent = TypeVar("TEvent", bound=Event)
@@ -42,7 +48,7 @@ class Repository(Generic[TAggregate]):
42
48
  with aggregate.__persisting_changes__() as pending:
43
49
  start_from = old_version + 1
44
50
  events = [
45
- Metadata.wrap(event, version)
51
+ WrappedEvent.wrap(event, version)
46
52
  for version, event in enumerate(pending, start=start_from)
47
53
  ]
48
54
 
@@ -9,7 +9,7 @@ __all__ = [
9
9
  "ExplicitVersioning",
10
10
  "InMemoryBackendFactory",
11
11
  "Listener",
12
- "Metadata",
12
+ "WrappedEvent",
13
13
  "NO_VERSIONING",
14
14
  "Position",
15
15
  "RawEvent",
@@ -31,11 +31,11 @@ from event_sourcery.event_store.event import (
31
31
  Entry,
32
32
  Event,
33
33
  EventRegistry,
34
- Metadata,
35
34
  Position,
36
35
  RawEvent,
37
36
  Recorded,
38
37
  RecordedRaw,
38
+ WrappedEvent,
39
39
  )
40
40
  from event_sourcery.event_store.event_store import EventStore
41
41
  from event_sourcery.event_store.factory import (
@@ -3,14 +3,14 @@ from collections.abc import Callable
3
3
 
4
4
  from event_sourcery.event_store.event import (
5
5
  Event,
6
- Metadata,
7
6
  Position,
8
7
  RecordedRaw,
9
8
  Serde,
9
+ WrappedEvent,
10
10
  )
11
11
  from event_sourcery.event_store.stream_id import StreamId
12
12
 
13
- Listener = Callable[[Metadata, StreamId, Position | None], None]
13
+ Listener = Callable[[WrappedEvent, StreamId, Position | None], None]
14
14
 
15
15
 
16
16
  class Dispatcher:
@@ -22,10 +22,10 @@ class Dispatcher:
22
22
  for raw in raws:
23
23
  record = self._serde.deserialize_record(raw)
24
24
  for event_type, listeners in self._listeners.items():
25
- if not isinstance(record.metadata.event, event_type):
25
+ if not isinstance(record.wrapped_event.event, event_type):
26
26
  continue
27
27
  for listener in listeners:
28
- listener(record.metadata, record.stream_id, record.position)
28
+ listener(record.wrapped_event, record.stream_id, record.position)
29
29
 
30
30
  def register(self, listener: Listener, to: type[Event]) -> None:
31
31
  self._listeners[to].add(listener)
@@ -3,7 +3,7 @@ __all__ = [
3
3
  "Entry",
4
4
  "Event",
5
5
  "EventRegistry",
6
- "Metadata",
6
+ "WrappedEvent",
7
7
  "Position",
8
8
  "RawEvent",
9
9
  "Recorded",
@@ -16,11 +16,11 @@ from event_sourcery.event_store.event.dto import (
16
16
  Context,
17
17
  Entry,
18
18
  Event,
19
- Metadata,
20
19
  Position,
21
20
  RawEvent,
22
21
  Recorded,
23
22
  RecordedRaw,
23
+ WrappedEvent,
24
24
  )
25
25
  from event_sourcery.event_store.event.registry import EventRegistry
26
26
  from event_sourcery.event_store.event.serde import Serde
@@ -35,6 +35,7 @@ class Event(BaseModel, extra="forbid"):
35
35
  order_id: OrderId
36
36
  ```
37
37
  """
38
+
38
39
  __registry__: ClassVar = EventRegistry()
39
40
 
40
41
  def __init_subclass__(cls, **kwargs: Any) -> None:
@@ -49,7 +50,7 @@ class Context(BaseModel, extra="allow"):
49
50
  causation_id: UUID | None = None
50
51
 
51
52
 
52
- class Metadata(BaseModel, Generic[TEvent], extra="forbid"):
53
+ class WrappedEvent(BaseModel, Generic[TEvent], extra="forbid"):
53
54
  """Wrapper for events with all relevant metadata.
54
55
 
55
56
  Returned from EventStore when loading events from a stream.
@@ -60,9 +61,10 @@ class Metadata(BaseModel, Generic[TEvent], extra="forbid"):
60
61
  order_id: OrderId
61
62
 
62
63
  event = OrderCancelled(order_id=OrderId("#123"))
63
- metadata = Metadata.wrap(event, version=1)
64
+ wrapped_event = WrappedEvent.wrap(event, version=1)
64
65
  ```
65
66
  """
67
+
66
68
  event: TEvent
67
69
  version: int | None
68
70
  uuid: UUID = Field(default_factory=uuid4)
@@ -70,12 +72,12 @@ class Metadata(BaseModel, Generic[TEvent], extra="forbid"):
70
72
  context: Context = Field(default_factory=Context)
71
73
 
72
74
  @classmethod
73
- def wrap(cls, event: TEvent, version: int | None) -> "Metadata[TEvent]":
74
- return Metadata[TEvent](event=event, version=version)
75
+ def wrap(cls, event: TEvent, version: int | None) -> "WrappedEvent[TEvent]":
76
+ return WrappedEvent[TEvent](event=event, version=version)
75
77
 
76
78
 
77
79
  class Entry(BaseModel):
78
- metadata: Metadata
80
+ wrapped_event: WrappedEvent
79
81
  stream_id: StreamId
80
82
 
81
83
 
@@ -4,10 +4,10 @@ from typing import cast
4
4
 
5
5
  from event_sourcery.event_store.event.dto import (
6
6
  Event,
7
- Metadata,
8
7
  RawEvent,
9
8
  Recorded,
10
9
  RecordedRaw,
10
+ WrappedEvent,
11
11
  )
12
12
  from event_sourcery.event_store.event.registry import EventRegistry
13
13
  from event_sourcery.event_store.stream_id import StreamId
@@ -17,27 +17,27 @@ from event_sourcery.event_store.stream_id import StreamId
17
17
  class Serde:
18
18
  registry: EventRegistry
19
19
 
20
- def deserialize(self, event: RawEvent) -> Metadata:
20
+ def deserialize(self, event: RawEvent) -> WrappedEvent:
21
21
  event_as_dict = dict(event)
22
22
  del event_as_dict["stream_id"]
23
23
  del event_as_dict["name"]
24
24
  data = cast(Mapping, event_as_dict.pop("data"))
25
25
  event_type = self.registry.type_for_name(event.name)
26
- return Metadata[event_type]( # type: ignore
26
+ return WrappedEvent[event_type]( # type: ignore
27
27
  **event_as_dict,
28
28
  event=event_type(**data),
29
29
  )
30
30
 
31
31
  def deserialize_record(self, record: RecordedRaw) -> Recorded:
32
32
  return Recorded(
33
- metadata=self.deserialize(record.entry),
33
+ wrapped_event=self.deserialize(record.entry),
34
34
  stream_id=record.entry.stream_id,
35
35
  position=record.position,
36
36
  )
37
37
 
38
38
  def serialize(
39
39
  self,
40
- event: Metadata,
40
+ event: WrappedEvent,
41
41
  stream_id: StreamId,
42
42
  ) -> RawEvent:
43
43
  model = cast(Event, event.event)
@@ -2,7 +2,13 @@ from collections.abc import Sequence
2
2
  from functools import singledispatchmethod
3
3
  from typing import cast
4
4
 
5
- from event_sourcery.event_store.event import Event, Metadata, Position, RawEvent, Serde
5
+ from event_sourcery.event_store.event import (
6
+ Event,
7
+ Position,
8
+ RawEvent,
9
+ Serde,
10
+ WrappedEvent,
11
+ )
6
12
  from event_sourcery.event_store.interfaces import StorageStrategy
7
13
  from event_sourcery.event_store.stream_id import StreamId
8
14
  from event_sourcery.event_store.versioning import (
@@ -24,16 +30,16 @@ class EventStore:
24
30
  stream_id: StreamId,
25
31
  start: int | None = None,
26
32
  stop: int | None = None,
27
- ) -> Sequence[Metadata]:
33
+ ) -> Sequence[WrappedEvent]:
28
34
  """Loads events from a given stream.
29
35
 
30
36
  Examples:
31
37
  >>> load_stream(stream_id=StreamId(name="not_existing_stream"))
32
38
  []
33
39
  >>> load_stream(stream_id=StreamId(name="existing_stream"))
34
- [Metadata(..., version=1), Metadata(...), Metadata(..., version=3)]
40
+ [WrappedEvent(..., version=1), ..., WrappedEvent(..., version=3)]
35
41
  >>> load_stream(stream_id=StreamId(name="existing_stream"), start=2, stop=3)
36
- [Metadata(..., version=2)]
42
+ [WrappedEvent(..., version=2)]
37
43
 
38
44
  Args:
39
45
  stream_id: The stream identifier to load events from.
@@ -49,8 +55,8 @@ class EventStore:
49
55
  @singledispatchmethod
50
56
  def append(
51
57
  self,
52
- first: Metadata,
53
- *events: Metadata,
58
+ first: WrappedEvent,
59
+ *events: WrappedEvent,
54
60
  stream_id: StreamId,
55
61
  expected_version: int | Versioning = 0,
56
62
  ) -> None:
@@ -60,13 +66,13 @@ class EventStore:
60
66
  To use it, pass the expected version of the stream.
61
67
 
62
68
  Examples:
63
- >>> append(Metadata(...), stream_id=StreamId())
69
+ >>> append(WrappedEvent(...), stream_id=StreamId())
64
70
  None
65
- >>> append(Metadata(...), stream_id=StreamId(), expected_version=1)
71
+ >>> append(WrappedEvent(...), stream_id=StreamId(), expected_version=1)
66
72
  None
67
73
 
68
74
  Args:
69
- first: The first event to append (Metadata or Event).
75
+ first: The first event to append (WrappedEvent or Event).
70
76
  *events: The rest of the events to append (same type as first argument).
71
77
  stream_id: The stream identifier to append events to.
72
78
  expected_version: The expected version of the stream
@@ -99,22 +105,22 @@ class EventStore:
99
105
  self,
100
106
  expected_version: int,
101
107
  events: Sequence[Event],
102
- ) -> Sequence[Metadata]:
108
+ ) -> Sequence[WrappedEvent]:
103
109
  return [
104
- Metadata.wrap(event=event, version=version)
110
+ WrappedEvent.wrap(event=event, version=version)
105
111
  for version, event in enumerate(events, start=expected_version + 1)
106
112
  ]
107
113
 
108
114
  @_wrap_events.register
109
115
  def _wrap_events_versioning(
110
116
  self, expected_version: Versioning, events: Sequence[Event]
111
- ) -> Sequence[Metadata]:
112
- return [Metadata.wrap(event=event, version=None) for event in events]
117
+ ) -> Sequence[WrappedEvent]:
118
+ return [WrappedEvent.wrap(event=event, version=None) for event in events]
113
119
 
114
120
  def _append(
115
121
  self,
116
122
  stream_id: StreamId,
117
- events: Sequence[Metadata],
123
+ events: Sequence[WrappedEvent],
118
124
  expected_version: int | Versioning,
119
125
  ) -> None:
120
126
  new_version = events[-1].version
@@ -152,13 +158,13 @@ class EventStore:
152
158
  """
153
159
  self._storage_strategy.delete_stream(stream_id)
154
160
 
155
- def save_snapshot(self, stream_id: StreamId, snapshot: Metadata) -> None:
161
+ def save_snapshot(self, stream_id: StreamId, snapshot: WrappedEvent) -> None:
156
162
  """Saves a snapshot of the stream.
157
163
 
158
164
  Examples:
159
- >>> save_snapshot(StreamId(), Metadata(...))
165
+ >>> save_snapshot(StreamId(), WrappedEvent(...))
160
166
  None
161
- >>> save_snapshot(StreamId(name="not_existing_stream"), Metadata(...))
167
+ >>> save_snapshot(StreamId(name="not_existing_stream"), WrappedEvent(...))
162
168
  None
163
169
 
164
170
  Args:
@@ -172,12 +178,12 @@ class EventStore:
172
178
  serialized = self._serde.serialize(event=snapshot, stream_id=stream_id)
173
179
  self._storage_strategy.save_snapshot(serialized)
174
180
 
175
- def _deserialize_events(self, events: list[RawEvent]) -> list[Metadata]:
181
+ def _deserialize_events(self, events: list[RawEvent]) -> list[WrappedEvent]:
176
182
  return [self._serde.deserialize(e) for e in events]
177
183
 
178
184
  def _serialize_events(
179
185
  self,
180
- events: Sequence[Metadata],
186
+ events: Sequence[WrappedEvent],
181
187
  stream_id: StreamId,
182
188
  ) -> list[RawEvent]:
183
189
  return [self._serde.serialize(event=e, stream_id=stream_id) for e in events]
@@ -19,7 +19,7 @@ class Outbox:
19
19
  with entry as raw_record:
20
20
  event = self._serde.deserialize(raw_record.entry)
21
21
  record = Recorded(
22
- metadata=event,
22
+ wrapped_event=event,
23
23
  stream_id=raw_record.entry.stream_id,
24
24
  position=raw_record.position,
25
25
  )
@@ -110,6 +110,6 @@ class SubscriptionBuilder(PositionPhase, FilterPhase, BuildPhase):
110
110
  ) -> Iterator[list[Recorded]]:
111
111
  seconds = self._to_timedelta(timelimit)
112
112
  subscription = self._build(batch_size=size, timelimit=seconds)
113
- return (
113
+ return ( # pragma: no cover # apparently, bug in coverage.py
114
114
  [self._serde.deserialize_record(e) for e in batch] for batch in subscription
115
115
  )
@@ -1,10 +1,10 @@
1
1
  from collections.abc import Callable
2
2
  from typing import TypeAlias
3
3
 
4
- from event_sourcery.event_store import Event, EventStore, Metadata, StreamId
4
+ from event_sourcery.event_store import Event, EventStore, StreamId, WrappedEvent
5
5
  from event_sourcery.read_model.cursors_dao import CursorsDao
6
6
 
7
- ReadModel: TypeAlias = Callable[[Metadata, StreamId], None]
7
+ ReadModel: TypeAlias = Callable[[WrappedEvent, StreamId], None]
8
8
 
9
9
 
10
10
  class Projector:
@@ -23,38 +23,38 @@ class Projector:
23
23
  self._cursors_dao = cursors_dao
24
24
  self._read_model = read_model
25
25
 
26
- def project(self, metadata: Metadata[Event], stream_id: StreamId) -> None:
27
- if metadata.version is None:
26
+ def project(self, wrapped_event: WrappedEvent[Event], stream_id: StreamId) -> None:
27
+ if wrapped_event.version is None:
28
28
  raise self.CantProjectUnversionedEvent
29
29
 
30
30
  try:
31
31
  self._cursors_dao.increment(
32
- name=self._name, stream_id=stream_id, version=metadata.version
32
+ name=self._name, stream_id=stream_id, version=wrapped_event.version
33
33
  )
34
- self._read_model(metadata, stream_id)
34
+ self._read_model(wrapped_event, stream_id)
35
35
  except self._cursors_dao.StreamNotTracked:
36
36
  self._cursors_dao.put_at(
37
- name=self._name, stream_id=stream_id, version=metadata.version
37
+ name=self._name, stream_id=stream_id, version=wrapped_event.version
38
38
  )
39
39
  missed_events = self._event_store.load_stream(
40
- stream_id=stream_id, stop=metadata.version
40
+ stream_id=stream_id, stop=wrapped_event.version
41
41
  )
42
42
  for event in missed_events:
43
43
  self._read_model(event, stream_id)
44
44
 
45
- self._read_model(metadata, stream_id)
45
+ self._read_model(wrapped_event, stream_id)
46
46
  except self._cursors_dao.BehindStream as exc:
47
47
  self._cursors_dao.move_to(
48
- name=self._name, stream_id=stream_id, version=metadata.version
48
+ name=self._name, stream_id=stream_id, version=wrapped_event.version
49
49
  )
50
50
  missed_events = self._event_store.load_stream(
51
51
  stream_id=stream_id,
52
52
  start=exc.current_version + 1,
53
- stop=metadata.version,
53
+ stop=wrapped_event.version,
54
54
  )
55
55
  for event in missed_events:
56
56
  self._read_model(event, stream_id)
57
57
 
58
- self._read_model(metadata, stream_id)
58
+ self._read_model(wrapped_event, stream_id)
59
59
  except self._cursors_dao.AheadOfStream:
60
60
  return
@@ -6,7 +6,7 @@ from itertools import islice
6
6
 
7
7
  from esdbclient import EventStoreDBClient, RecordedEvent
8
8
  from esdbclient.exceptions import DeadlineExceeded, NotFound
9
- from esdbclient.persistent import PersistentSubscription
9
+ from esdbclient.persistent import AbstractPersistentSubscription
10
10
 
11
11
  from event_sourcery.event_store import RecordedRaw
12
12
  from event_sourcery.event_store.interfaces import (
@@ -25,7 +25,7 @@ class ESDBOutboxStorageStrategy(OutboxStorageStrategy):
25
25
  _outbox_name: str
26
26
  _max_publish_attempts: int
27
27
  _timeout: float | None
28
- _active_subscription: PersistentSubscription = field(init=False)
28
+ _active_subscription: AbstractPersistentSubscription = field(init=False)
29
29
 
30
30
  def create_subscription(self) -> None:
31
31
  try:
@@ -51,7 +51,7 @@ class ESDBOutboxStorageStrategy(OutboxStorageStrategy):
51
51
  delattr(self, "_active_subscription")
52
52
 
53
53
  @property
54
- def active_subscription(self) -> PersistentSubscription:
54
+ def active_subscription(self) -> AbstractPersistentSubscription:
55
55
  return self._active_subscription
56
56
 
57
57
  def outbox_entries(
@@ -1,7 +1,8 @@
1
- from collections.abc import Callable, Iterator
1
+ from collections.abc import Iterator
2
2
  from dataclasses import dataclass
3
3
  from datetime import timedelta
4
4
  from functools import partial
5
+ from typing import Protocol
5
6
 
6
7
  import esdbclient.exceptions
7
8
  from esdbclient import EventStoreDBClient, RecordedEvent
@@ -11,13 +12,19 @@ from event_sourcery.event_store.interfaces import SubscriptionStrategy
11
12
  from event_sourcery_esdb import dto
12
13
 
13
14
 
15
+ class BuilderCallable(Protocol):
16
+ def __call__(
17
+ self, commit_position: Position | None = None
18
+ ) -> Iterator[RecordedEvent]: ...
19
+
20
+
14
21
  @dataclass(repr=False)
15
22
  class ESDBSubscriptionStrategy(SubscriptionStrategy):
16
23
  _client: EventStoreDBClient
17
24
 
18
25
  @staticmethod
19
26
  def _iterator(
20
- builder: Callable[[], Iterator[RecordedEvent]],
27
+ builder: BuilderCallable,
21
28
  size: int,
22
29
  ) -> Iterator[list[RecordedRaw]]:
23
30
  subscription = builder()
@@ -38,7 +38,7 @@ class SqlAlchemyCursorsDao(CursorsDao):
38
38
  .values({ProjectorCursor.version: version})
39
39
  )
40
40
  result = self._session.execute(update_stmt)
41
- if result.rowcount == 1: # type: ignore
41
+ if result.rowcount == 1:
42
42
  return
43
43
  else:
44
44
  current_version = self._current_version(name, stream_id)
@@ -155,7 +155,7 @@ class SqlAlchemyStorageStrategy(StorageStrategy):
155
155
  )
156
156
  result = self._session.execute(bump_version_stmt)
157
157
 
158
- if result.rowcount != 1: # type: ignore
158
+ if result.rowcount != 1:
159
159
  # optimistic lock failed
160
160
  raise ConcurrentStreamWriteError
161
161
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-event-sourcery"
3
- version = "0.4.0a4"
3
+ version = "0.4.0a6"
4
4
  description = ""
5
5
  authors = ["Your Name <you@example.com>"]
6
6
  license = "MIT"