def test_get_item(self):
        # Setup an event store.
        event_store = self.construct_event_store()

        # Put an event in the event store.
        entity_id = uuid4()
        event_store.store(
            Example.Created(
                a=1,
                b=2,
                originator_id=entity_id,
                originator_topic=get_topic(Example),
            ))

        # Construct a repository.
        event_sourced_repo = EventSourcedRepository(event_store=event_store)

        # Check the entity attributes.
        example = event_sourced_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Setup an example repository, using the subclass ExampleRepository.
        example_repo = ExampleRepository(event_store=event_store)

        # Check the repo has the example.
        self.assertIn(entity_id, example_repo)
        self.assertNotIn(uuid4(), example_repo)

        # Check the entity attributes.
        example = example_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)
Example #2
0
    def test_get_item(self):
        # Setup an event store.
        event_store = self.construct_event_store()

        # Put an event in the event store.
        entity_id = uuid4()
        event_store.append(Example.Created(entity_id=entity_id, a=1, b=2))

        # Check ValueError is raised if repo doesn't have a mutator function...
        with self.assertRaises(ValueError):
            EventSourcedRepository(event_store=event_store, mutator=None)
        # ...and isn't if we pass a mutator function as a constructor arg.
        event_sourced_repo = EventSourcedRepository(event_store=event_store,
                                                    mutator=Example.mutate)

        # Check the entity attributes.
        example = event_sourced_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Setup an example repository, using the subclass ExampleRepository.
        example_repo = ExampleRepository(event_store=event_store)

        # Check the repo has the example.
        self.assertIn(entity_id, example_repo)
        self.assertNotIn(uuid4(), example_repo)

        # Check the entity attributes.
        example = example_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)
Example #3
0
 def __init__(self, **kwargs):
     super(ExampleApplication, self).__init__(**kwargs)
     self.snapshot_strategy = EventSourcedSnapshotStrategy(
         event_store=self.timestamp_entity_event_store, )
     self.example_repo = ExampleRepository(
         event_store=self.version_entity_event_store,
         snapshot_strategy=self.snapshot_strategy,
     )
Example #4
0
 def __init__(self, **kwargs):
     super(ExampleApplication, self).__init__(**kwargs)
     self.snapshot_strategy = None
     if self.snapshot_event_store:
         self.snapshot_strategy = EventSourcedSnapshotStrategy(
             snapshot_store=self.snapshot_event_store)
     assert self.entity_event_store is not None
     self.example_repository = ExampleRepository(
         event_store=self.entity_event_store,
         snapshot_strategy=self.snapshot_strategy,
     )
Example #5
0
 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)
Example #6
0
 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 test_get_item(self) -> None:
        # Setup an event store.
        event_store = self.construct_event_store()

        # Put an event in the event store.
        entity_id = uuid4()
        event_store.store_events([
            Example.Created(
                a=1,
                b=2,
                originator_id=entity_id,
                originator_topic=get_topic(Example),
            )
        ])

        # Construct a repository.
        event_sourced_repo: EventSourcedRepository[
            Example,
            Example.Event] = EventSourcedRepository(event_store=event_store)

        # Check the entity attributes.
        example = event_sourced_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Check class-specific request.
        example = event_sourced_repo.get_instance_of(Example, entity_id)
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Check class-specific request fails on type.
        class SubExample(Example):
            pass

        self.assertIsNone(
            event_sourced_repo.get_instance_of(SubExample, entity_id))

        # Setup an example repository, using the subclass ExampleRepository.
        example_repo = ExampleRepository(event_store=event_store)

        # Check the repo has the example.
        self.assertIn(entity_id, example_repo)
        self.assertNotIn(uuid4(), example_repo)

        # Check the entity attributes.
        example = example_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)
 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)
Example #9
0
 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)
Example #10
0
 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 __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)
Example #12
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = Example.__create__(a=1, b=2)

        self.assertIsInstance(example1, Example)

        # Check the instance is equal to itself.
        self.assertEqual(example1, example1)

        # Check the instance is equal to a clone of itself.
        clone = object.__new__(type(example1))
        clone.__dict__.update(example1.__dict__)
        self.assertEqual(example1, clone)

        # Check the properties of the Example class.
        self.assertEqual(1, example1.a)
        self.assertEqual(2, example1.b)

        # Check the properties of the TimestampedVersionedEntity class.
        self.assertTrue(example1.id)
        self.assertEqual(example1.__version__, 0)
        self.assertTrue(example1.__created_on__)
        self.assertLess(example1.__created_on__, time.time())
        self.assertGreater(example1.__created_on__, time.time() - 1)
        self.assertTrue(example1.__last_modified__)
        self.assertEqual(example1.__created_on__, example1.__last_modified__)

        # Test the datetime_from_timestamp() converts ok.
        tt = time.time()
        dt = datetime.datetime.utcnow()
        self.assertEqual(datetime_from_timestamp(tt).hour, dt.hour)

        # Check can get datetime from timestamps, and it corresponds to UTC.
        dt = datetime_from_timestamp(example1.__created_on__)
        self.assertLess(dt, datetime.datetime.utcnow())
        self.assertGreater(dt,
                           datetime.datetime.utcnow() - datetime.timedelta(1))

        # Check a different type with the same values is not "equal" to the first.
        class Subclass(Example):
            pass

        other = object.__new__(Subclass)
        other.__dict__.update(example1.__dict__)
        self.assertEqual(example1.__dict__, other.__dict__)
        self.assertNotEqual(example1, other)

        # Check a second instance with the same values is not "equal" to the first.
        example2 = create_new_example(a=1, b=2)
        self.assertEqual(type(example1), type(example2))
        self.assertNotEqual(example1, example2)

        # Check entity not hashable.
        with self.assertRaises(TypeError):
            hash(example1)

        # Setup the repo.
        repo = ExampleRepository(self.entity_event_store)

        # Check the example entities can be retrieved from the example repository.
        entity1 = repo[example1.id]
        self.assertIsInstance(entity1, Example)
        self.assertEqual(1, entity1.a)
        self.assertEqual(2, entity1.b)

        entity2 = repo[example2.id]
        self.assertIsInstance(entity2, Example)
        self.assertEqual(1, entity2.a)
        self.assertEqual(2, entity2.b)

        # Check the entity can be updated.
        entity1.a = 100
        self.assertEqual(100, repo[entity1.id].a)
        entity1.b = -200
        self.assertEqual(-200, repo[entity1.id].b)

        self.assertEqual(repo[entity1.id].__created_on__,
                         entity1.__created_on__)
        self.assertEqual(repo[entity1.id].__last_modified__,
                         entity1.__last_modified__)
        self.assertNotEqual(entity1.__last_modified__, entity1.__created_on__)

        self.assertEqual(0, entity1.count_heartbeats())
        entity1.beat_heart()
        entity1.beat_heart()
        entity1.beat_heart()
        self.assertEqual(3, entity1.count_heartbeats())
        self.assertEqual(3, repo[entity1.id].count_heartbeats())

        # Check the entity can publish multiple events simultaneously.
        entity1.beat_heart(number_of_beats=3)
        self.assertEqual(6, repo[entity1.id].count_heartbeats())

        # Check the entity can be discarded.
        entity1.__discard__()

        # Check the repo now raises a KeyError.
        self.assertRaises(RepositoryKeyError, repo.__getitem__, entity1.id)

        # Check the entity can't be discarded twice.
        self.assertRaises(AssertionError, entity1.__discard__)

        # Should fail to validate event with wrong entity ID.
        with self.assertRaises(OriginatorIDError):
            VersionedEntity.Event(
                originator_id=uuid4(),
                originator_version=0,
            ).__check_obj__(entity2)
        # Should fail to validate event with wrong entity version.
        with self.assertRaises(OriginatorVersionError):
            VersionedEntity.Event(
                originator_id=entity2.id,
                originator_version=0,
                __previous_hash__=entity2.__head__,
            ).__check_obj__(entity2)

        # Should validate event with correct entity ID and version.
        VersionedEntity.Event(
            originator_id=entity2.id,
            originator_version=entity2.__version__ + 1,
            __previous_hash__=entity2.__head__,
        ).__check_obj__(entity2)

        # Check an entity cannot be reregistered with the ID of a discarded entity.
        replacement_event = Example.Created(
            originator_id=entity1.id,
            a=11,
            b=12,
            originator_topic=get_topic(Example),
        )
        with self.assertRaises(ConcurrencyError):
            publish(event=replacement_event)
Example #13
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = create_new_example(a=1, b=2)
        self.assertIsInstance(example1, Example)

        # Check the instance is equal to itself.
        self.assertEqual(example1, example1)

        # Check the instance is equal to a clone of itself.
        clone = object.__new__(type(example1))
        clone.__dict__.update(example1.__dict__)
        self.assertEqual(example1, clone)

        # Check the properties of the Example class.
        self.assertEqual(1, example1.a)
        self.assertEqual(2, example1.b)

        # Check the properties of the TimestampedVersionedEntity class.
        self.assertTrue(example1.id)
        self.assertEqual(1, example1.version)
        self.assertTrue(example1.created_on)
        self.assertTrue(example1.last_modified)
        self.assertEqual(example1.created_on, example1.last_modified)

        # Check a different type with the same values is not "equal" to the first.
        class Subclass(Example):
            pass

        other = object.__new__(Subclass)
        other.__dict__.update(example1.__dict__)
        self.assertEqual(example1.__dict__, other.__dict__)
        self.assertNotEqual(example1, other)

        # Check a second instance with the same values is not "equal" to the first.
        example2 = create_new_example(a=1, b=2)
        self.assertEqual(type(example1), type(example2))
        self.assertNotEqual(example1, example2)

        # Setup the repo.
        repo = ExampleRepository(self.entity_event_store)

        # Check the example entities can be retrieved from the example repository.
        entity1 = repo[example1.id]
        self.assertIsInstance(entity1, Example)
        self.assertEqual(1, entity1.a)
        self.assertEqual(2, entity1.b)

        entity2 = repo[example2.id]
        self.assertIsInstance(entity2, Example)
        self.assertEqual(1, entity2.a)
        self.assertEqual(2, entity2.b)

        # Check the entity can be updated.
        entity1.a = 100
        self.assertEqual(100, repo[entity1.id].a)
        entity1.b = -200
        self.assertEqual(-200, repo[entity1.id].b)

        self.assertEqual(repo[entity1.id].created_on, entity1.created_on)
        self.assertEqual(repo[entity1.id].last_modified, entity1.last_modified)
        self.assertNotEqual(entity1.last_modified, entity1.created_on)

        self.assertEqual(0, entity1.count_heartbeats())
        entity1.beat_heart()
        entity1.beat_heart()
        entity1.beat_heart()
        self.assertEqual(3, entity1.count_heartbeats())
        self.assertEqual(3, repo[entity1.id].count_heartbeats())

        # Check the entity can publish multiple events simultaneously.
        entity1.beat_heart(number_of_beats=3)
        self.assertEqual(6, repo[entity1.id].count_heartbeats())

        # Check the entity can be discarded.
        entity1.discard()

        # Check the repo now raises a KeyError.
        self.assertRaises(RepositoryKeyError, repo.__getitem__, entity1.id)

        # Check the entity can't be discarded twice.
        self.assertRaises(AssertionError, entity1.discard)

        # Should fail to validate event with wrong entity ID.
        with self.assertRaises(MismatchedOriginatorIDError):
            entity2._validate_originator(
                VersionedEntity.Event(originator_id=uuid4(),
                                      originator_version=0))
        # Should fail to validate event with wrong entity version.
        with self.assertRaises(MismatchedOriginatorVersionError):
            entity2._validate_originator(
                VersionedEntity.Event(
                    originator_id=entity2.id,
                    originator_version=0,
                ))

        # Should validate event with correct entity ID and version.
        entity2._validate_originator(
            VersionedEntity.Event(
                originator_id=entity2.id,
                originator_version=entity2.version,
            ))

        # Check an entity cannot be reregistered with the ID of a discarded entity.
        replacement_event = Example.Created(originator_id=entity1.id,
                                            a=11,
                                            b=12)
        with self.assertRaises(ConcurrencyError):
            publish(event=replacement_event)