Пример #1
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = register_new_example(a=1, b=2)
        self.assertIsInstance(example1, Example)
        self.assertEqual(1, example1.a)
        self.assertEqual(2, example1.b)

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

        # Setup the repo.
        repo = ExampleRepository(self.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(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 be discarded.
        entity1.discard()
        self.assertRaises(KeyError, repo.__getitem__, entity1.id)
Пример #2
0
    def test_with_snapshots(self):
        # Check the EventPlayer's take_snapshot() method.
        stored_event_repo = PythonObjectsStoredEventRepository()
        event_store = EventStore(stored_event_repo)
        self.ps = PersistenceSubscriber(event_store)
        event_player = EventPlayer(
            event_store=event_store,
            id_prefix='Example',
            mutate_func=Example.mutate,
            snapshot_strategy=EventSourcedSnapshotStrategy(
                event_store=event_store))

        # Check the method returns None when there are no events.
        snapshot = event_player.take_snapshot('wrong')
        self.assertIsNone(snapshot)

        # Create a new entity.
        example = register_new_example(a=123, b=234)

        # Take a snapshot with the entity.
        snapshot1 = event_player.take_snapshot(example.id)
        self.assertIsInstance(snapshot1, Snapshot)

        # Take another snapshot with the entity.
        snapshot2 = event_player.take_snapshot(example.id)
        # - should return the previous snapshot
        self.assertIsInstance(snapshot2, Snapshot)
        self.assertEqual(snapshot2.at_event_id, snapshot1.at_event_id)

        # Generate a domain event.
        example.beat_heart()

        # Take another snapshot with the entity.
        # - should use the previous snapshot and the heartbeat event
        snapshot3 = event_player.take_snapshot(example.id)
        self.assertNotEqual(snapshot3.at_event_id, snapshot1.at_event_id)
    def test_with_snapshots(self):
        # Check the EventPlayer's take_snapshot() method.
        stored_event_repo = PythonObjectsStoredEventRepository()
        event_store = EventStore(stored_event_repo)
        self.ps = PersistenceSubscriber(event_store)
        event_player = EventPlayer(
            event_store=event_store,
            id_prefix='Example',
            mutate_func=Example.mutate,
            snapshot_strategy=EventSourcedSnapshotStrategy(event_store=event_store)
        )

        # Check the method returns None when there are no events.
        snapshot = event_player.take_snapshot('wrong')
        self.assertIsNone(snapshot)

        # Create a new entity.
        example = register_new_example(a=123, b=234)

        # Take a snapshot with the entity.
        snapshot1 = event_player.take_snapshot(example.id)
        self.assertIsInstance(snapshot1, Snapshot)

        # Take another snapshot with the entity.
        snapshot2 = event_player.take_snapshot(example.id)
        # - should return the previous snapshot
        self.assertIsInstance(snapshot2, Snapshot)
        self.assertEqual(snapshot2.at_event_id, snapshot1.at_event_id)

        # Generate a domain event.
        example.beat_heart()

        # Take another snapshot with the entity.
        # - should use the previous snapshot and the heartbeat event
        snapshot3 = event_player.take_snapshot(example.id)
        self.assertNotEqual(snapshot3.at_event_id, snapshot1.at_event_id)
Пример #4
0
 def register_new_example(self, a, b):
     return register_new_example(a=a, b=b)
Пример #5
0
 def register_new_example(self, a, b):
     return register_new_example(a=a, b=b)
Пример #6
0
    def test_entity_performance(self):
        """
        Reports on the performance of Example entity and repo.

        NB: This test doesn't actually check anything, so it isn't really a test.
        """

        # Initialise dict of entities.
        self.entities = {}

        report_name = type(self).__name__[4:]
        print("\n\n{} report:\n".format(report_name))

        repetitions = 10

        # NB: Use range(1, 5) to test whether we can get more than 10000 event from Cassandra.
        for i in six.moves.range(0, 5):
            # Setup a number of entities, with different lengths of event history.
            payload = 3
            # payload = str([uuid4().hex for _ in six.moves.range(100000)])
            example = register_new_example(a=1, b=payload)
            self.entities[i] = example

            # Beat a number of times.
            start_beating = utc_now()
            num_beats = int(floor(10 ** i))
            for _ in six.moves.range(num_beats):
                example.beat_heart()
            time_beating = utc_now() - start_beating
            print("Time to beat {} times: {:.2f}s ({:.0f} beats/s, {:.6f}s each)"
                  "".format(num_beats, time_beating, num_beats / time_beating, time_beating / num_beats))

            # Get the last n events from the repo.
            def last_n(n):
                n = min(n, num_beats + 1)
                stored_entity_id = make_stored_entity_id('Example', example.id)
                repo = self.app.example_repo.event_player.event_store.stored_event_repo

                start_last_n = utc_now()
                last_n_stored_events = []
                for _ in six.moves.range(repetitions):
                    last_n_stored_events = repo.get_most_recent_events(stored_entity_id, limit=n)
                time_last_n = (utc_now() - start_last_n) / repetitions

                num_retrieved_events = len(list(last_n_stored_events))
                events_per_second = num_retrieved_events / time_last_n
                print(("Time to get last {:>"+str(i+1)+"} events after {} events: {:.6f}s ({:.0f} events/s)"
                      "").format(n, num_beats + 1, time_last_n, events_per_second))

            for j in range(0, i+1):
                last_n(10**j)

            # Get the entity by replaying all events (which it must since there isn't a snapshot).
            start_replay = utc_now()
            for _ in six.moves.range(repetitions):
                example = self.app.example_repo[example.id]
                assert isinstance(example, Example)
                heartbeats = example.count_heartbeats()
                assert heartbeats == num_beats, (heartbeats, num_beats)

            time_replaying = (utc_now() - start_replay) / repetitions
            print("Time to replay {} beats: {:.2f}s ({:.0f} beats/s, {:.6f}s each)"
                  "".format(num_beats, time_replaying, num_beats / time_replaying, time_replaying / num_beats))

            # Take snapshot, and beat heart a few more times.
            self.app.example_repo.event_player.take_snapshot(example.id, until=uuid1().hex)

            extra_beats = 4
            for _ in six.moves.range(extra_beats):
                example.beat_heart()
            num_beats += extra_beats

            # Get the entity using snapshot and replaying events since the snapshot.
            start_replay = utc_now()
            for _ in six.moves.range(repetitions):
                example = self.app.example_repo[example.id]
            time_replaying = (utc_now() - start_replay) / repetitions

            events_per_second = (extra_beats + 1) / time_replaying  # +1 for the snapshot event
            beats_per_second = num_beats / time_replaying
            print("Time to replay snapshot with {} extra beats: {:.6f}s ({:.0f} events/s, {:.0f} beats/s)"
                  "".format(extra_beats, time_replaying, events_per_second, beats_per_second))
            
            print("")
Пример #7
0
    def test_snapshots(self):
        stored_event_repo = PythonObjectsStoredEventRepository()
        event_store = EventStore(stored_event_repo)
        self.ps = PersistenceSubscriber(event_store)
        event_player = EventPlayer(event_store=event_store,
                                   id_prefix='Example',
                                   mutate_func=Example.mutate)

        # Create a new entity.
        registered_example = register_new_example(a=123, b=234)

        # Take a snapshot.
        snapshot = take_snapshot(registered_example, uuid1().hex)

        # Replay from this snapshot.
        after = snapshot.at_event_id
        initial_state = entity_from_snapshot(snapshot)
        retrieved_example = event_player.replay_events(
            registered_example.id, initial_state=initial_state, after=after)

        # Check the attributes are correct.
        self.assertEqual(retrieved_example.a, 123)

        # Remember the time now.
        timecheck1 = uuid1().hex

        # Change attribute value.
        retrieved_example.a = 999

        # Check the initial state doesn't move.
        self.assertEqual(initial_state.a, 123)

        # Remember the time now.
        timecheck2 = uuid1().hex

        # Change attribute value.
        retrieved_example.a = 9999

        # Remember the time now.
        timecheck3 = uuid1().hex

        # Check the event sourced entities are correct.
        assert initial_state.a == 123
        retrieved_example = event_player.replay_events(registered_example.id)
        self.assertEqual(retrieved_example.a, 9999)

        # Take another snapshot.
        snapshot2 = take_snapshot(retrieved_example, uuid1().hex)

        # Check we can replay from this snapshot.
        initial_state2 = entity_from_snapshot(snapshot2)
        after2 = snapshot2.domain_event_id
        retrieved_example = event_player.replay_events(
            registered_example.id, initial_state=initial_state2, after=after2)
        # Check the attributes are correct.
        self.assertEqual(retrieved_example.a, 9999)

        # Check we can get historical state at timecheck1.
        retrieved_example = event_player.replay_events(registered_example.id,
                                                       until=timecheck1)
        self.assertEqual(retrieved_example.a, 123)

        # Check we can get historical state at timecheck2.
        retrieved_example = event_player.replay_events(registered_example.id,
                                                       until=timecheck2)
        self.assertEqual(retrieved_example.a, 999)

        # Check we can get historical state at timecheck3.
        retrieved_example = event_player.replay_events(registered_example.id,
                                                       until=timecheck3)
        self.assertEqual(retrieved_example.a, 9999)

        # Similarly, check we can get historical state using a snapshot
        retrieved_example = event_player.replay_events(
            registered_example.id,
            initial_state=initial_state,
            after=after,
            until=timecheck2)
        self.assertEqual(retrieved_example.a, 999)
    def test_snapshots(self):
        stored_event_repo = PythonObjectsStoredEventRepository()
        event_store = EventStore(stored_event_repo)
        self.ps = PersistenceSubscriber(event_store)
        event_player = EventPlayer(event_store=event_store, id_prefix='Example', mutate_func=Example.mutate)

        # Create a new entity.
        registered_example = register_new_example(a=123, b=234)

        # Take a snapshot.
        snapshot = take_snapshot(registered_example, uuid1().hex)

        # Replay from this snapshot.
        after = snapshot.at_event_id
        initial_state = entity_from_snapshot(snapshot)
        retrieved_example = event_player.replay_events(registered_example.id, initial_state=initial_state, after=after)

        # Check the attributes are correct.
        self.assertEqual(retrieved_example.a, 123)

        # Remember the time now.
        timecheck1 = uuid1().hex

        # Change attribute value.
        retrieved_example.a = 999

        # Check the initial state doesn't move.
        self.assertEqual(initial_state.a, 123)

        # Remember the time now.
        timecheck2 = uuid1().hex

        # Change attribute value.
        retrieved_example.a = 9999

        # Remember the time now.
        timecheck3 = uuid1().hex

        # Check the event sourced entities are correct.
        assert initial_state.a == 123
        retrieved_example = event_player.replay_events(registered_example.id)
        self.assertEqual(retrieved_example.a, 9999)

        # Take another snapshot.
        snapshot2 = take_snapshot(retrieved_example, uuid1().hex)

        # Check we can replay from this snapshot.
        initial_state2 = entity_from_snapshot(snapshot2)
        after2 = snapshot2.domain_event_id
        retrieved_example = event_player.replay_events(registered_example.id, initial_state=initial_state2, after=after2)
        # Check the attributes are correct.
        self.assertEqual(retrieved_example.a, 9999)

        # Check we can get historical state at timecheck1.
        retrieved_example = event_player.replay_events(registered_example.id, until=timecheck1)
        self.assertEqual(retrieved_example.a, 123)

        # Check we can get historical state at timecheck2.
        retrieved_example = event_player.replay_events(registered_example.id, until=timecheck2)
        self.assertEqual(retrieved_example.a, 999)

        # Check we can get historical state at timecheck3.
        retrieved_example = event_player.replay_events(registered_example.id, until=timecheck3)
        self.assertEqual(retrieved_example.a, 9999)

        # Similarly, check we can get historical state using a snapshot
        retrieved_example = event_player.replay_events(registered_example.id, initial_state=initial_state, after=after, until=timecheck2)
        self.assertEqual(retrieved_example.a, 999)
Пример #9
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = register_new_example(a=1, b=2)
        self.assertIsInstance(example1, Example)

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

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

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

        # Setup the repo.
        repo = ExampleRepo(self.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(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 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.
        self.assertRaises(
            EntityIDConsistencyError, entity2._validate_originator,
            DomainEvent(entity_id=entity2.id + 'wrong', entity_version=0))
        # Should fail to validate event with wrong entity version.
        self.assertRaises(EntityVersionConsistencyError,
                          entity2._validate_originator,
                          DomainEvent(entity_id=entity2.id, entity_version=0))
        # Should validate event with correct entity ID and version.
        entity2._validate_originator(
            DomainEvent(entity_id=entity2.id, entity_version=entity2.version))

        # Check an entity can be reregistered with the same ID.
        replacement_event = Example.Created(entity_id=entity1.id, a=11, b=12)
        # replacement = Example.mutate(event=replacement_event)
        publish(event=replacement_event)

        # Check the replacement entity can be retrieved from the example repository.
        replacement = repo[entity1.id]
        assert isinstance(replacement, Example)
        self.assertEqual(replacement.a, 11)
        self.assertEqual(replacement.b, 12)
Пример #10
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = register_new_example(a=1, b=2)
        self.assertIsInstance(example1, Example)

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

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

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

        # Setup the repo.
        repo = ExampleRepo(self.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(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 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.
        self.assertRaises(EntityIDConsistencyError,
                          entity2._validate_originator,
                          DomainEvent(entity_id=entity2.id+'wrong', entity_version=0)
                          )
        # Should fail to validate event with wrong entity version.
        self.assertRaises(EntityVersionConsistencyError,
                          entity2._validate_originator,
                          DomainEvent(entity_id=entity2.id, entity_version=0)
                          )
        # Should validate event with correct entity ID and version.
        entity2._validate_originator(
            DomainEvent(entity_id=entity2.id, entity_version=entity2.version)
        )

        # Check an entity can be reregistered with the same ID.
        replacement_event = Example.Created(entity_id=entity1.id, a=11, b=12)
        # replacement = Example.mutate(event=replacement_event)
        publish(event=replacement_event)

        # Check the replacement entity can be retrieved from the example repository.
        replacement = repo[entity1.id]
        assert isinstance(replacement, Example)
        self.assertEqual(replacement.a, 11)
        self.assertEqual(replacement.b, 12)