class ExampleApplicationWithAlternativeSequencedItemType(object): def __init__(self, session): self.event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=session, active_record_class=StoredEventRecord, sequenced_item_class=StoredEvent, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=StoredEvent, sequence_id_attr_name='originator_id', position_attr_name='originator_version', ) ) self.repository = ExampleRepository( event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store) def close(self): self.persistence_policy.close() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close()
class ExampleApplicationWithTimeuuidSequencedItems(object): def __init__(self): self.event_store = EventStore( active_record_strategy=CassandraActiveRecordStrategy( active_record_class=CqlTimeuuidSequencedItem, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='event_id', ) ) self.repository = EventSourcedRepository( mutator=ExampleEntity._mutate, event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store) def start_entity(self): return ExampleEntity.start() def close(self): self.persistence_policy.close() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close()
class TestPersistencePolicy(unittest.TestCase): def setUp(self): self.event_store = mock.Mock(spec=AbstractEventStore) self.persistence_policy = PersistencePolicy( event_store=self.event_store, event_type=VersionedEntity.Event ) def tearDown(self): self.persistence_policy.close() def test_published_events_are_appended_to_event_store(self): # Check the event store's append method has NOT been called. assert isinstance(self.event_store, AbstractEventStore) self.assertEqual(0, self.event_store.append.call_count) # Publish a versioned entity event. entity_id = uuid4() domain_event1 = VersionedEntity.Event(originator_id=entity_id, originator_version=0) publish(domain_event1) # Check the append method has been called once with the domain event. self.event_store.append.assert_called_once_with(domain_event1) # Publish a timestamped entity event (should be ignored). domain_event2 = TimestampedEntity.Event(originator_id=entity_id) publish(domain_event2) # Check the append() has still only been called once with the first domain event. self.event_store.append.assert_called_once_with(domain_event1)
def setUp(self): super(WithPersistencePolicies, self).setUp() # Setup the persistence subscriber. self.entity_event_store = EventStore( active_record_strategy=self.entity_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version' ) ) self.log_event_store = EventStore( active_record_strategy=self.log_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='timestamp' ) ) self.snapshot_store = EventStore( active_record_strategy=self.snapshot_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version' ) ) self.integer_sequenced_event_policy = None if self.entity_event_store is not None: self.integer_sequenced_event_policy = PersistencePolicy( event_store=self.entity_event_store, event_type=VersionedEntity.Event, ) self.timestamp_sequenced_event_policy = None if self.log_event_store is not None: self.timestamp_sequenced_event_policy = PersistencePolicy( event_store=self.log_event_store, event_type=Logged, ) self.snapshot_policy = None if self.snapshot_store is not None: self.snapshot_policy = PersistencePolicy( event_store=self.snapshot_store, event_type=Snapshot, )
class ExampleDDDApplication(object): def __init__(self, datastore): event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=datastore.session, active_record_class=IntegerSequencedItemRecord, ), sequenced_item_mapper=SequencedItemMapper( sequence_id_attr_name='originator_id', position_attr_name='originator_version', ) ) self.aggregate_repository = EventSourcedRepository( mutator=ExampleAggregateRoot._mutate, event_store=event_store, ) self.persistence_policy = PersistencePolicy( event_type=ExampleAggregateRoot.Event, event_store=event_store, ) def create_example_aggregate(self): """ Factory method, creates and returns a new example aggregate root object. :rtype: ExampleAggregateRoot """ event = ExampleAggregateRoot.Created(originator_id=uuid.uuid4()) aggregate = ExampleAggregateRoot._mutate(initial=None, event=event) aggregate._pending_events.append(event) return aggregate def close(self): self.persistence_policy.close() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close()
class ExampleApplicationWithAlternativeSequencedItemType(object): def __init__(self): self.event_store = EventStore( active_record_strategy=CassandraActiveRecordStrategy( active_record_class=StoredEventRecord, sequenced_item_class=StoredEvent, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=StoredEvent, other_attr_names=(), ) ) self.repository = ExampleRepository( event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.persistence_policy.close()
def __init__(self): self.event_store = EventStore( active_record_strategy=CassandraActiveRecordStrategy( active_record_class=StoredEventRecord, sequenced_item_class=StoredEvent, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=StoredEvent, other_attr_names=(), ) ) self.repository = ExampleRepository( event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def __init__(self, session): self.event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=session, active_record_class=StoredEventRecord, sequenced_item_class=StoredEvent, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=StoredEvent, sequence_id_attr_name='originator_id', position_attr_name='originator_version', ) ) self.repository = ExampleRepository( event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def __init__(self): self.event_store = EventStore( active_record_strategy=CassandraActiveRecordStrategy( active_record_class=CqlTimeuuidSequencedItem, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='event_id', ) ) self.repository = EventSourcedRepository( mutator=ExampleEntity._mutate, event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def __init__(self, datastore): event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=datastore.session, active_record_class=IntegerSequencedItemRecord, ), sequenced_item_mapper=SequencedItemMapper( sequence_id_attr_name='originator_id', position_attr_name='originator_version', ) ) self.aggregate_repository = EventSourcedRepository( mutator=ExampleAggregateRoot._mutate, event_store=event_store, ) self.persistence_policy = PersistencePolicy( event_type=ExampleAggregateRoot.Event, event_store=event_store, )
def setUp(self): self.event_store = mock.Mock(spec=AbstractEventStore) self.persistence_policy = PersistencePolicy( event_store=self.event_store, event_type=VersionedEntity.Event )
class WithPersistencePolicies(WithActiveRecordStrategies): """ Base class for test cases that need persistence policies. """ def setUp(self): super(WithPersistencePolicies, self).setUp() # Setup the persistence subscriber. self.entity_event_store = EventStore( active_record_strategy=self.entity_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version' ) ) self.log_event_store = EventStore( active_record_strategy=self.log_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='timestamp' ) ) self.snapshot_store = EventStore( active_record_strategy=self.snapshot_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version' ) ) self.integer_sequenced_event_policy = None if self.entity_event_store is not None: self.integer_sequenced_event_policy = PersistencePolicy( event_store=self.entity_event_store, event_type=VersionedEntity.Event, ) self.timestamp_sequenced_event_policy = None if self.log_event_store is not None: self.timestamp_sequenced_event_policy = PersistencePolicy( event_store=self.log_event_store, event_type=Logged, ) self.snapshot_policy = None if self.snapshot_store is not None: self.snapshot_policy = PersistencePolicy( event_store=self.snapshot_store, event_type=Snapshot, ) def tearDown(self): # Close the persistence subscriber. if self.snapshot_policy: self.snapshot_policy.close() if self.timestamp_sequenced_event_policy: self.timestamp_sequenced_event_policy.close() if self.entity_event_store: self.integer_sequenced_event_policy.close() super(WithPersistencePolicies, self).tearDown()
def test_take_snapshot(self): self.entity_persistence_policy = PersistencePolicy( event_store=self.entity_event_store, event_type=VersionedEntity.Event, ) self.snapshot_persistence_policy = PersistencePolicy( event_store=self.snapshot_store, event_type=Snapshot, ) snapshot_strategy = EventSourcedSnapshotStrategy( event_store=self.snapshot_store) event_player = EventPlayer(event_store=self.entity_event_store, mutator=Example._mutate, snapshot_strategy=snapshot_strategy) # Take a snapshot with a non-existent ID. unregistered_id = uuid4() # Check no snapshot is taken. self.assertIsNone(event_player.take_snapshot(unregistered_id)) # Check no snapshot is available. self.assertIsNone(event_player.get_snapshot(unregistered_id)) # Create a new entity. registered_example = create_new_example(a=123, b=234) # Take a snapshot of the new entity (no previous snapshots). snapshot1 = event_player.take_snapshot(registered_example.id, lt=registered_example.version) # Take another snapshot of the entity (should be the same event). sleep(0.0001) snapshot2 = event_player.take_snapshot(registered_example.id, lt=registered_example.version) self.assertEqual(snapshot1, snapshot2) # Check the snapshot is pegged to the last applied version. self.assertEqual(snapshot1.originator_version, 0) # Replay from this snapshot. entity_from_snapshot1 = entity_from_snapshot(snapshot1) retrieved_example = event_player.replay_entity( registered_example.id, initial_state=entity_from_snapshot1, gte=entity_from_snapshot1._version) # Check the attributes are correct. self.assertEqual(retrieved_example.a, 123) # Remember the version now. version1 = retrieved_example._version self.assertEqual(version1, 1) # Change attribute value. retrieved_example.a = 999 # Remember the version now. version2 = retrieved_example._version self.assertEqual(version2, 2) # Change attribute value. retrieved_example.a = 9999 # Remember the version now. version3 = retrieved_example._version self.assertEqual(version3, 3) # Check the event sourced entities are correct. retrieved_example = event_player.replay_entity(registered_example.id) self.assertEqual(retrieved_example.a, 9999) # Take another snapshot. snapshot3 = event_player.take_snapshot(retrieved_example.id, lt=retrieved_example.version) # Replay from this snapshot. initial_state = entity_from_snapshot(snapshot3) retrieved_example = event_player.replay_entity( registered_example.id, initial_state=initial_state, gte=initial_state._version, ) # Check the attributes are correct. self.assertEqual(retrieved_example.a, 9999) # Check we can get historical state at version1. retrieved_example = event_player.replay_entity(registered_example.id, lt=version1) self.assertEqual(retrieved_example.a, 123) # Check we can get historical state at version2. retrieved_example = event_player.replay_entity(registered_example.id, lt=version2) self.assertEqual(retrieved_example.a, 999) # Check we can get historical state at version3. retrieved_example = event_player.replay_entity(registered_example.id, lt=version3) self.assertEqual(retrieved_example.a, 9999) # Similarly, check we can get historical state using a snapshot initial_state = entity_from_snapshot(snapshot1) retrieved_example = event_player.replay_entity( registered_example.id, initial_state=initial_state, gte=initial_state._version, lt=version2, ) self.assertEqual(retrieved_example.a, 999) # Discard the entity. registered_example = event_player.replay_entity(registered_example.id) registered_example.discard() # Take snapshot of discarded entity. snapshot4 = event_player.take_snapshot(registered_example.id) self.assertIsNone(snapshot4.state) self.assertIsNone(entity_from_snapshot(snapshot4))