class TestSnapshottingPolicy(unittest.TestCase): def setUp(self): self.repository: AbstractEntityRepository = mock.Mock( spec=AbstractEntityRepository) self.snapshot_store: AbstractEventStore = mock.Mock( spec=AbstractEventStore) self.policy = SnapshottingPolicy(repository=self.repository, snapshot_store=self.snapshot_store, period=2) def tearDown(self): self.policy.close() def test_published_events_are_appended_to_event_store(self): # Check the event store's append method has NOT been called. self.assertEqual(0, self.repository.take_snapshot.call_count) # Publish a versioned entity event. entity_id = uuid4() domain_event1 = VersionedEntity.Event(originator_id=entity_id, originator_version=0) domain_event2 = VersionedEntity.Event(originator_id=entity_id, originator_version=1) # Check take_snapshot is called once for each event. publish([domain_event1]) self.assertEqual(0, self.repository.take_snapshot.call_count) publish([domain_event2]) self.assertEqual(1, self.repository.take_snapshot.call_count) # Check take_snapshot is called once for each list. publish([domain_event1, domain_event2]) self.assertEqual(2, self.repository.take_snapshot.call_count)
class SnapshottingApplication(SimpleApplication): # Todo: Change this to default to None? snapshot_period = 2 def __init__(self, snapshot_period=None, snapshot_record_class=None, **kwargs): self.snapshot_period = snapshot_period or self.snapshot_period self.snapshot_record_class = snapshot_record_class self.snapshotting_policy = None self.snapshot_store = None self.snapshot_strategy = None self.snapshotting_policy = None super(SnapshottingApplication, self).__init__(**kwargs) def construct_event_store(self): super(SnapshottingApplication, self).construct_event_store() # Setup event store for snapshots. self.snapshot_store = EventStore( record_manager=self.infrastructure_factory. construct_snapshot_record_manager(), sequenced_item_mapper=self.sequenced_item_mapper_class( sequenced_item_class=self.sequenced_item_class)) def construct_repository(self, **kwargs): # Setup repository with a snapshot strategy. self.snapshot_strategy = EventSourcedSnapshotStrategy( snapshot_store=self.snapshot_store) super(SnapshottingApplication, self).construct_repository( snapshot_strategy=self.snapshot_strategy, **kwargs) def construct_persistence_policy(self): super(SnapshottingApplication, self).construct_persistence_policy() self.snapshotting_policy = SnapshottingPolicy( repository=self.repository, snapshot_store=self.snapshot_store, persist_event_type=self.persist_event_type, period=self.snapshot_period) def setup_table(self): super(SnapshottingApplication, self).setup_table() if self.datastore is not None: self.datastore.setup_table( self.snapshot_store.record_manager.record_class) def drop_table(self): super(SnapshottingApplication, self).drop_table() if self.datastore is not None: self.datastore.drop_table( self.snapshot_store.record_manager.record_class) def close(self): super(SnapshottingApplication, self).close() if self.snapshotting_policy is not None: self.snapshotting_policy.close() self.snapshotting_policy = None
class SnapshottingApplication(SimpleApplication): def __init__(self, period=10, snapshot_record_class=None, **kwargs): self.period = period self.snapshot_record_class = snapshot_record_class super(SnapshottingApplication, self).__init__(**kwargs) def setup_event_store(self): super(SnapshottingApplication, self).setup_event_store() # Setup snapshot store, using datastore session, and SnapshotRecord class. # Todo: Refactor this into a new create_sqlalchemy_snapshotstore() function. self.snapshot_store = EventStore( SQLAlchemyRecordManager( session=self.datastore.session, record_class=self.snapshot_record_class or SnapshotRecord ), SequencedItemMapper( sequence_id_attr_name='originator_id', position_attr_name='originator_version' ) ) def setup_repository(self, **kwargs): # Setup repository with a snapshot strategy. self.snapshot_strategy = EventSourcedSnapshotStrategy( event_store=self.snapshot_store ) super(SnapshottingApplication, self).setup_repository( snapshot_strategy=self.snapshot_strategy, **kwargs ) def setup_persistence_policy(self, persist_event_type): persist_event_type = persist_event_type or DomainEntity.Event super(SnapshottingApplication, self).setup_persistence_policy(persist_event_type) self.snapshotting_policy = SnapshottingPolicy(self.repository, self.period) self.snapshot_persistence_policy = PersistencePolicy( event_store=self.snapshot_store, event_type=Snapshot ) def setup_table(self): super(SnapshottingApplication, self).setup_table() # Also setup snapshot table. self.datastore.setup_table(self.snapshot_store.record_manager.record_class) def close(self): super(SnapshottingApplication, self).close() self.snapshotting_policy.close() self.snapshot_persistence_policy.close()
class SnapshottingApplication(SimpleApplication[TVersionedEntity, TVersionedEvent]): snapshot_period = 0 def __init__(self, snapshot_period: int = 0, **kwargs: Any): self.snapshot_period = snapshot_period or self.snapshot_period self.snapshot_store: Optional[AbstractEventStore[ AbstractSnapshot, AbstractRecordManager]] = None self.snapshot_strategy: Optional[EventSourcedSnapshotStrategy] = None self.snapshotting_policy: Optional[SnapshottingPolicy] = None super(SnapshottingApplication, self).__init__(**kwargs) def construct_event_store(self) -> None: super(SnapshottingApplication, self).construct_event_store() # Setup event store for snapshots. assert self.infrastructure_factory record_manager = self.infrastructure_factory.construct_snapshot_record_manager( ) assert self.sequenced_item_mapper_class is not None assert self.sequenced_item_class is not None self.snapshot_store = EventStore( record_manager=record_manager, event_mapper=self.event_store.event_mapper) def construct_repository(self, **kwargs: Any) -> None: # Setup repository with a snapshot strategy. assert self.snapshot_store self.snapshot_strategy = EventSourcedSnapshotStrategy( snapshot_store=self.snapshot_store) super(SnapshottingApplication, self).construct_repository( snapshot_strategy=self.snapshot_strategy, **kwargs) def construct_persistence_policy(self) -> None: super(SnapshottingApplication, self).construct_persistence_policy() assert self.snapshot_store self.snapshotting_policy = SnapshottingPolicy( repository=self.repository, snapshot_store=self.snapshot_store, persist_event_type=self.persist_event_type, period=self.snapshot_period, ) def setup_table(self) -> None: super(SnapshottingApplication, self).setup_table() if self._datastore is not None: assert self.snapshot_store self._datastore.setup_table( self.snapshot_store.record_manager.record_class) def drop_table(self) -> None: super(SnapshottingApplication, self).drop_table() if self._datastore is not None: assert self.snapshot_store self._datastore.drop_table( self.snapshot_store.record_manager.record_class) def close(self) -> None: super(SnapshottingApplication, self).close() if self.snapshotting_policy is not None: self.snapshotting_policy.close() self.snapshotting_policy = None