def setUp(self): super(WithPersistencePolicies, self).setUp() # Setup the persistence subscriber. self.entity_event_store = EventStore( record_manager=self.entity_record_manager, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version' ) ) self.log_event_store = EventStore( record_manager=self.log_record_manager, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='timestamp' ) ) self.snapshot_store = EventStore( record_manager=self.snapshot_record_manager, 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 construct_sqlalchemy_eventstore( session, sequenced_item_class=StoredEvent, sequence_id_attr_name=None, position_attr_name=None, json_encoder_class=ObjectJSONEncoder, json_decoder_class=ObjectJSONDecoder, always_encrypt=False, cipher=None, active_record_class=StoredEventRecord, ): sequenced_item_mapper = SequencedItemMapper( sequenced_item_class=sequenced_item_class, sequence_id_attr_name=sequence_id_attr_name, position_attr_name=position_attr_name, json_encoder_class=json_encoder_class, json_decoder_class=json_decoder_class, always_encrypt=always_encrypt, cipher=cipher, ) active_record_strategy = SQLAlchemyActiveRecordStrategy( session=session, active_record_class=active_record_class, sequenced_item_class=sequenced_item_class, ) event_store = EventStore( active_record_strategy=active_record_strategy, sequenced_item_mapper=sequenced_item_mapper, ) return event_store
def construct_sqlalchemy_eventstore( session, sequenced_item_class=None, sequence_id_attr_name=None, position_attr_name=None, json_encoder_class=None, json_decoder_class=None, cipher=None, record_class=None, contiguous_record_ids=False, ): sequenced_item_class = sequenced_item_class or StoredEvent sequenced_item_mapper = SequencedItemMapper( sequenced_item_class=sequenced_item_class, sequence_id_attr_name=sequence_id_attr_name, position_attr_name=position_attr_name, json_encoder_class=json_encoder_class, json_decoder_class=json_decoder_class, cipher=cipher, ) factory = SQLAlchemyInfrastructureFactory( session=session, integer_sequenced_record_class=record_class or StoredEventRecord, sequenced_item_class=sequenced_item_class, contiguous_record_ids=contiguous_record_ids, ) record_manager = factory.construct_integer_sequenced_record_manager() event_store = EventStore( record_manager=record_manager, sequenced_item_mapper=sequenced_item_mapper, ) return event_store
def construct_event_store(self): event_store = EventStore(record_manager=self.factory. construct_integer_sequenced_record_manager(), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version')) return event_store
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 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 construct_event_store(self): event_store = EventStore( active_record_strategy= construct_integer_sequenced_active_record_strategy( datastore=self.datastore, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version')) return event_store
def construct_event_store(self): event_store = EventStore( active_record_strategy= construct_integer_sequenced_active_record_strategy( datastore=self.datastore, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, event_sequence_id_attr='entity_id', event_position_attr='entity_version', )) return event_store
def __init__(self): self.event_store = EventStore( record_manager=CassandraRecordManager( record_class=StoredEventRecord, sequenced_item_class=StoredEvent), event_mapper=SequencedItemMapper(sequenced_item_class=StoredEvent, other_attr_names=()), ) self.repository = ExampleRepository(event_store=self.event_store) self.persistence_policy = PersistencePolicy( event_store=self.event_store, persist_event_type=DomainEvent)
def create_event_store(db) -> EventStore: record_manager = SQLAlchemyRecordManager(session=db.session, sequenced_item_class=StoredEvent, record_class=StoredEventRecord, application_name="CompanyApp", contiguous_record_ids=True) event_mapper = SequencedItemMapper(sequenced_item_class=StoredEvent, cipher=cipher) event_store = EventStore(record_manager=record_manager, event_mapper=event_mapper) return event_store
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 setUp(self): super(WithPersistencePolicy, self).setUp() # Setup the persistence subscriber. self.versioned_entity_event_store = EventStore( active_record_strategy=self. integer_sequence_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, event_sequence_id_attr='entity_id', event_position_attr='entity_version')) self.timestamped_entity_event_store = EventStore( active_record_strategy=self. timestamp_sequence_active_record_strategy, sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, event_sequence_id_attr='entity_id', event_position_attr='timestamp')) self.persistence_policy = CombinedPersistencePolicy( versioned_entity_event_store=self.versioned_entity_event_store, timestamped_entity_event_store=self.timestamped_entity_event_store, )
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 __init__(self, datastore): event_store = EventStore( record_manager=SQLAlchemyRecordManager( session=datastore.session, record_class=IntegerSequencedNoIDRecord), event_mapper=SequencedItemMapper( sequence_id_attr_name="originator_id", position_attr_name="originator_version", ), ) self.repository = EventSourcedRepository(event_store=event_store) self.persistence_policy = PersistencePolicy( persist_event_type=ExampleAggregateRoot.Event, event_store=event_store)
def construct_event_store(self, event_sequence_id_attr, event_position_attr, active_record_strategy, always_encrypt=False, cipher=None): sequenced_item_mapper = self.construct_sequenced_item_mapper( sequenced_item_class=active_record_strategy.sequenced_item_class, event_sequence_id_attr=event_sequence_id_attr, event_position_attr=event_position_attr, always_encrypt=always_encrypt, cipher=cipher ) event_store = EventStore( active_record_strategy=active_record_strategy, sequenced_item_mapper=sequenced_item_mapper, ) return event_store
def __init__(self, datastore): self.event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( datastore=datastore, active_record_class=SqlExtendedIntegerSequencedItem, sequenced_item_class=ExtendedSequencedItem, ), sequenced_item_mapper=ExtendedSequencedItemMapper( sequenced_item_class=ExtendedSequencedItem, event_sequence_id_attr='entity_id', event_position_attr='entity_version', )) self.repository = ExampleRepository(event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def __init__(self): self.event_store = EventStore( record_manager=CassandraRecordManager( record_class=TimeuuidSequencedRecord, sequenced_item_class=SequencedItem), event_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name="originator_id", position_attr_name="event_id", ), ) self.repository = EventSourcedRepository(event_store=self.event_store) self.persistence_policy = PersistencePolicy( event_store=self.event_store, persist_event_type=DomainEvent)
def construct_event_store(self, sequenced_item_mapper_class, event_sequence_id_attr, event_position_attr, record_manager, cipher=None): sequenced_item_mapper = self.construct_sequenced_item_mapper( sequenced_item_mapper_class=sequenced_item_mapper_class, sequenced_item_class=record_manager.sequenced_item_class, event_sequence_id_attr=event_sequence_id_attr, event_position_attr=event_position_attr, cipher=cipher, ) event_store = EventStore( record_manager=record_manager, sequenced_item_mapper=sequenced_item_mapper, ) return event_store
def __init__(self, session): self.event_store = EventStore( record_manager=SQLAlchemyRecordManager( session=session, 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, session): self.event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=session, active_record_class=ExtendedIntegerSequencedItemRecord, sequenced_item_class=ExtendedSequencedItem, ), sequenced_item_mapper=ExtendedSequencedItemMapper( sequenced_item_class=ExtendedSequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version', other_attr_names=('timestamp', ), )) self.repository = ExampleRepository(event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def setUp(self): assert_event_handlers_empty() super(TestEventPlayer, self).setUp() self.datastore.setup_connection() self.datastore.setup_tables() # Setup an event store for versioned entity events. self.entity_event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=self.datastore.session, active_record_class=IntegerSequencedItemRecord, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version', ), ) # Setup an event store for snapshots. self.snapshot_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=self.datastore.session, active_record_class=SnapshotRecord, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version', ), ) self.entity_persistence_policy = None self.snapshot_persistence_policy = None
def setUp(self): assert_event_handlers_empty() super(TestEventPlayer, self).setUp() self.datastore.setup_connection() self.datastore.setup_tables() # Setup an event store for version entity events. self.version_entity_event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( datastore=self.datastore, active_record_class=SqlIntegerSequencedItem, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, event_sequence_id_attr='entity_id', event_position_attr='entity_version', ), ) # Setup an event store for timestamp entity events. self.timestamp_entity_event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( datastore=self.datastore, active_record_class=SqlTimestampSequencedItem, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, event_sequence_id_attr='entity_id', event_position_attr='timestamp', ), ) self.policy = None
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, event_sequence_id_attr='entity_id', event_position_attr='event_id', )) self.repository = EventSourcedRepository( mutator=ExampleEntity.mutate, event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def __init__(self): self.event_store = EventStore( record_manager=CassandraRecordManager( record_class=TimeuuidSequencedRecord, 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( event_store=self.event_store, ) self.persistence_policy = PersistencePolicy(self.event_store)
def __init__(self, datastore): event_store = EventStore( record_manager=SQLAlchemyRecordManager( session=datastore.session, record_class=IntegerSequencedNoIDRecord ), event_mapper=SequencedItemMapper( sequence_id_attr_name="originator_id", position_attr_name="originator_version", ), ) # Todo: Remove having two repositories, because they are identical. self.aggregate1_repository = AggregateRepository(event_store=event_store) self.aggregate2_repository = AggregateRepository(event_store=event_store) self.persistence_policy = PersistencePolicy( persist_event_type=ExampleAggregateRoot.Event, event_store=event_store )
def setup_event_store(self): # Construct event store. sequenced_item_mapper = self.sequenced_item_mapper_class( sequenced_item_class=self.sequenced_item_class, cipher=self.cipher, # sequence_id_attr_name=sequence_id_attr_name, # position_attr_name=position_attr_name, json_encoder_class=self.json_encoder_class, json_decoder_class=self.json_decoder_class, ) record_manager = self.infrastructure_factory.construct_integer_sequenced_record_manager( ) self.event_store = EventStore( record_manager=record_manager, sequenced_item_mapper=sequenced_item_mapper, )
def __init__(self, session): self.event_store = EventStore( record_manager=SQLAlchemyRecordManager( session=session, record_class=ExtendedIntegerSequencedRecord, sequenced_item_class=ExtendedSequencedItem, ), event_mapper=ExtendedSequencedItemMapper( sequenced_item_class=ExtendedSequencedItem, sequence_id_attr_name="originator_id", position_attr_name="originator_version", other_attr_names=("timestamp", ), ), ) self.repository = ExampleRepository(event_store=self.event_store) self.persistence_policy = PersistencePolicy( event_store=self.event_store, persist_event_type=DomainEvent)
def __init__(self, datastore): event_store = EventStore(record_manager=SQLAlchemyRecordManager( session=datastore.session, record_class=IntegerSequencedNoIDRecord, ), sequenced_item_mapper=SequencedItemMapper( sequence_id_attr_name='originator_id', position_attr_name='originator_version', )) self.aggregate1_repository = AggregateRepository( event_store=event_store, ) self.aggregate2_repository = AggregateRepository( event_store=event_store, ) self.persistence_policy = PersistencePolicy( event_type=ExampleAggregateRoot.Event, event_store=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, )
class TestEventPlayer(SQLAlchemyDatastoreTestCase): def setUp(self): assert_event_handlers_empty() super(TestEventPlayer, self).setUp() self.datastore.setup_connection() self.datastore.setup_tables() # Setup an event store for versioned entity events. self.entity_event_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=self.datastore.session, active_record_class=IntegerSequencedItemRecord, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version', ), ) # Setup an event store for snapshots. self.snapshot_store = EventStore( active_record_strategy=SQLAlchemyActiveRecordStrategy( session=self.datastore.session, active_record_class=SnapshotRecord, sequenced_item_class=SequencedItem, ), sequenced_item_mapper=SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version', ), ) self.entity_persistence_policy = None self.snapshot_persistence_policy = None def tearDown(self): self.datastore.drop_tables() self.datastore.drop_connection() if self.entity_persistence_policy is not None: self.entity_persistence_policy.close() if self.snapshot_persistence_policy is not None: self.snapshot_persistence_policy.close() super(TestEventPlayer, self).tearDown() assert_event_handlers_empty() def test_replay_entity(self): # Store example events. # Create entity1. entity_id1 = uuid4() event1 = Example.Created(originator_id=entity_id1, a=1, b=2) self.entity_event_store.append(event1) # Create entity2. entity_id2 = uuid4() event2 = Example.Created(originator_id=entity_id2, a=2, b=4) self.entity_event_store.append(event2) # Create entity3. entity_id3 = uuid4() event3 = Example.Created(originator_id=entity_id3, a=3, b=6) self.entity_event_store.append(event3) # Discard entity3. event4 = Example.Discarded(originator_id=entity_id3, originator_version=1) self.entity_event_store.append(event4) # Check the entities can be replayed. event_player = EventPlayer(event_store=self.entity_event_store, mutator=Example._mutate) # Check recovered entities have correct attribute values. recovered1 = event_player.replay_entity(entity_id1) self.assertEqual(entity_id1, recovered1.id) self.assertEqual(1, recovered1.a) recovered2 = event_player.replay_entity(entity_id2) self.assertEqual(2, recovered2.a) recovered3 = event_player.replay_entity(entity_id3) self.assertEqual(None, recovered3) # Check it works for "short" entities (should be faster, but the main thing is that it still works). # - just use a trivial mutate that always instantiates the 'Example'. event5 = Example.AttributeChanged(originator_id=entity_id1, originator_version=1, name='a', value=10) self.entity_event_store.append(event5) recovered1 = event_player.replay_entity(entity_id1) self.assertEqual(10, recovered1.a) event_player = EventPlayer( event_store=self.entity_event_store, mutator=Example._mutate, is_short=True, ) self.assertEqual(10, event_player.replay_entity(entity_id1).a) 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) # 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. snapshot2 = event_player.take_snapshot(retrieved_example.id, lt=retrieved_example.version) # Replay from this snapshot. initial_state = entity_from_snapshot(snapshot2) 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. snapshot3 = event_player.take_snapshot(registered_example.id) self.assertIsNone(snapshot3.state) self.assertIsNone(entity_from_snapshot(snapshot3))
import uuid from eventsourcing.infrastructure.sequenceditemmapper import SequencedItemMapper from eventsourcing.infrastructure.eventsourcedrepository import EventSourcedRepository from eventsourcing.infrastructure.eventstore import EventStore from eventsourcing.infrastructure.sequenceditem import StoredEvent from eventsourcing.infrastructure.sqlalchemy.datastore import SQLAlchemyDatastore, SQLAlchemySettings from eventsourcing.infrastructure.sqlalchemy.manager import SQLAlchemyRecordManager from eventsourcing.infrastructure.sqlalchemy.records import StoredEventRecord datastore = SQLAlchemyDatastore( tables=(StoredEventRecord, ), settings=SQLAlchemySettings(uri='sqlite:///mydatabase')) datastore.setup_connection() datastore.setup_tables() recordmanager = SQLAlchemyRecordManager(session=datastore.session, record_class=StoredEventRecord, application_name=uuid.uuid4().hex, contiguous_record_ids=True, sequenced_item_class=StoredEvent) sequenceitemmapper = SequencedItemMapper(sequenced_item_class=StoredEvent) eventstore = EventStore(record_manager=recordmanager, sequenced_item_mapper=sequenceitemmapper) repository = EventSourcedRepository(event_store=eventstore)