Ejemplo n.º 1
0
    def test_decimaltimestamp_corresponds_with_decimaltimestamp_from_uuid(
            self):
        if os.getenv("TRAVIS_PYTHON_VERSION") in [
                "3.6", "3.7", "3.7-dev", "pypy3.5"
        ]:
            self.skipTest("Somehow this fails on Travis dist:xenial.")

            # This is the weird error that happens in Python 3.7.1 on Travis Xenial dist.
            # Why does the second timestamp "happen" more than one second before the first?
            # Perhaps UUID1 doesn't actually use time.time() sometimes? Maybe it was a bug in v3.7.1?
            """
FAIL: test_decimaltimestamp_corresponds_with_decimaltimestamp_from_uuid (
eventsourcing.tests.core_tests.test_utils.TestUtils)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/build/johnbywater/eventsourcing/eventsourcing/tests/core_tests/test_utils.py", line 61,
  in test_decimaltimestamp_corresponds_with_decimaltimestamp_from_uuid
    self.assertLess(timestamp1, timestamp2)
AssertionError: Decimal('1561464862.322443') not less than Decimal('1561464861.100940')
            """

        timestamp1 = decimaltimestamp()
        sleep(0.000001)
        uuid_1 = uuid1()
        sleep(0.000001)
        timestamp3 = decimaltimestamp()
        sleep(0.000001)
        timestamp2 = decimaltimestamp_from_uuid(uuid_1)
        self.assertLess(timestamp1, timestamp2)
        self.assertLess(timestamp2, timestamp3)
    def test_with_timestamped_entity_event(self):
        # Setup the mapper, and create an event.
        mapper = SequencedItemMapper(
            sequenced_item_class=SequencedItem,
            sequence_id_attr_name="originator_id",
            position_attr_name="timestamp",
        )
        before = decimaltimestamp()
        sleep(0.000001)  # Avoid test failing due to timestamp having limited precision.
        event2 = Event2(originator_id="entity2")
        sleep(0.000001)  # Avoid test failing due to timestamp having limited precision.
        after = decimaltimestamp()

        # Check to_sequenced_item() method results in a sequenced item.
        sequenced_item = mapper.item_from_event(event2)
        self.assertIsInstance(sequenced_item, SequencedItem)
        self.assertGreater(sequenced_item.position, before)
        self.assertLess(sequenced_item.position, after)
        self.assertEqual(sequenced_item.sequence_id, "entity2")
        self.assertEqual(sequenced_item.topic, get_topic(Event2))
        self.assertTrue(sequenced_item.state)

        # Use the returned values to create a new sequenced item.
        sequenced_item_copy = SequencedItem(
            sequence_id=sequenced_item.sequence_id,
            position=sequenced_item.position,
            topic=sequenced_item.topic,
            state=sequenced_item.state,
        )

        # Check from_sequenced_item() returns an event.
        domain_event = mapper.event_from_item(sequenced_item_copy)
        self.assertIsInstance(domain_event, Event2)
        self.assertEqual(domain_event.originator_id, event2.originator_id)
        self.assertEqual(domain_event.timestamp, event2.timestamp)
    def test_one_subclass(self):
        # Check base class can be sub-classed.
        class Event(EventWithTimestamp, EventWithOriginatorID):
            pass

        # Check construction requires an ID.
        with self.assertRaises(TypeError):
            Event()

        # Get timestamp before events.
        time1 = decimaltimestamp()

        # Construct events.
        event1 = Event(originator_id="1")
        event2 = Event(originator_id="1")

        # Check the entity IDs.
        self.assertEqual(event1.originator_id, "1")
        self.assertEqual(event2.originator_id, "1")

        # Check the event timestamps.
        self.assertLessEqual(time1, event1.timestamp)
        self.assertLessEqual(event1.timestamp, event2.timestamp)
        self.assertLessEqual(event2.timestamp, decimaltimestamp())

        # Check the events are not equal to each other, whilst being equal to themselves.
        self.assertEqual(event1, event1)
        self.assertEqual(event2, event2)
        self.assertNotEqual(event1, event2)
Ejemplo n.º 4
0
    def test_timestamp_from_uuid(self):
        until = decimaltimestamp()
        uuid = uuid1()
        after = decimaltimestamp()
        uuid_timestamp = decimaltimestamp_from_uuid(uuid)
        self.assertLess(until, uuid_timestamp)
        self.assertGreater(after, uuid_timestamp)

        # Check timestamp_from_uuid() works with hex strings, as well as UUID objects.
        self.assertEqual(decimaltimestamp_from_uuid(uuid.hex),
                         decimaltimestamp_from_uuid(uuid))
Ejemplo n.º 5
0
    def test_decimaltimestamp(self):
        # Check a given float is correctly converted to a Decimal.
        self.assertEqual(decimaltimestamp(123456789.1234560),
                         Decimal("123456789.123456"))
        self.assertEqual(decimaltimestamp(1234567890.1234560),
                         Decimal("1234567890.123456"))

        # Generate a series of timestamps.
        timestamps = [decimaltimestamp() for _ in range(100)]

        # Check series doesn't decrease at any point.
        last = timestamps[0]
        for timestamp in timestamps[1:]:
            self.assertLessEqual(last, timestamp)
            last = timestamp
    def test(self):
        # Check base class can be sub-classed.
        class Event(EventWithTimeuuid):
            pass

        # Check event has a UUID event_id.
        event = Event()
        self.assertIsInstance(event.event_id, UUID)

        # Check the event_id can't be reassigned.
        with self.assertRaises(AttributeError):
            # noinspection PyPropertyAccess
            event.event_id = decimaltimestamp()

        # Check event can be instantiated with a given UUID.
        event_id = uuid1()
        event = Event(event_id=event_id)
        self.assertEqual(event.event_id, event_id)

        # Generate a series of timestamps.
        events = [Event() for _ in range(100)]
        timestamps = [decimaltimestamp_from_uuid(e.event_id) for e in events]

        # Check series doesn't decrease at any point.
        last = timestamps[0]
        for timestamp in timestamps[1:]:
            self.assertLessEqual(last, timestamp)
            last = timestamp

        # Check last timestamp is greater than the first.
        self.assertGreater(timestamps[-1], timestamps[0])
Ejemplo n.º 7
0
 def log_message(self, message: str) -> "MessageLogged":
     assert isinstance(message, str)
     bucket_id = make_timebucket_id(self.name, decimaltimestamp(),
                                    self.bucket_size)
     event = MessageLogged(originator_id=bucket_id, message=message)
     publish([event])
     return event
    def get_events(self,
                   gt=None,
                   gte=None,
                   lt=None,
                   lte=None,
                   limit=None,
                   is_ascending=False,
                   page_size=None):
        assert limit is None or limit > 0

        # Identify the first time bucket.
        now = decimaltimestamp()
        started_on = self.log.started_on
        absolute_latest = min(now, lt or now, lte or now)
        absolute_earlyist = max(started_on, gt or 0, gte or 0)
        if is_ascending:
            position = absolute_earlyist
        else:
            position = absolute_latest

        # Start counting events.
        count_events = 0

        while True:
            bucket_id = make_timebucket_id(self.log.name, position,
                                           self.log.bucket_size)
            for message_logged_event in self.event_store.get_domain_events(
                    originator_id=bucket_id,
                    gt=gt,
                    gte=gte,
                    lt=lt,
                    lte=lte,
                    limit=limit,
                    is_ascending=is_ascending,
                    page_size=page_size,
            ):
                yield message_logged_event

                if limit is not None:
                    count_events += 1
                    if count_events >= limit:
                        return

            # See if there's another bucket.
            if is_ascending:
                next_timestamp = next_bucket_starts(position,
                                                    self.log.bucket_size)
                if next_timestamp > absolute_latest:
                    return
                else:
                    position = next_timestamp
            else:
                if position < absolute_earlyist:
                    return
                else:
                    position = previous_bucket_starts(position,
                                                      self.log.bucket_size)
 def append_message(self, message):
     assert isinstance(message, six.string_types)
     bucket_id = make_timebucket_id(self.name, decimaltimestamp(),
                                    self.bucket_size)
     event = MessageLogged(
         originator_id=bucket_id,
         message=message,
     )
     publish(event)
     return event
    def test(self):
        # Check base class can be sub-classed.
        class Event(EventWithTimestamp):
            pass

        # Check event can be instantiated with a timestamp.
        time1 = decimaltimestamp()
        event = Event(timestamp=time1)
        self.assertEqual(event.timestamp, time1)

        # Check event can be instantiated without a timestamp.
        event = Event()
        self.assertGreaterEqual(event.timestamp, time1)
        self.assertLessEqual(event.timestamp, decimaltimestamp())

        # Check the timestamp value can't be reassigned.
        with self.assertRaises(AttributeError):
            # noinspection PyPropertyAccess
            event.timestamp = decimaltimestamp()
    def test(self):
        # Check base class can be sub-classed.
        class Event(EventWithTimeuuid):
            pass

        # Check event can be instantiated with an event_id.
        event_id = uuid1()
        event = Event(event_id=event_id)
        self.assertEqual(event.event_id, event_id)

        # Check event can be instantiated without an event_id.
        time1 = decimaltimestamp()
        event = Event()
        self.assertGreater(decimaltimestamp_from_uuid(event.event_id), time1)
        self.assertLess(decimaltimestamp_from_uuid(event.event_id),
                        decimaltimestamp())

        # Check the event_id can't be reassigned.
        with self.assertRaises(AttributeError):
            # noinspection PyPropertyAccess
            event.event_id = decimaltimestamp()
Ejemplo n.º 12
0
 def setup_sequenced_items(self):
     self.sequenced_items = []
     self.number_of_sequenced_items = 12
     for i in range(self.number_of_sequenced_items):
         sequenced_item = SequencedItem(
             sequence_id=self.entity_id,
             position=i,
             topic='eventsourcing.example.domain_model#Example.Created',
             state='{"i":%s,"entity_id":"%s","timestamp":%s}' %
             (i, self.entity_id, decimaltimestamp()),
         )
         self.sequenced_items.append(sequenced_item)
         self.entity_record_manager.record_sequenced_items(sequenced_item)
Ejemplo n.º 13
0
 def construct_positions(self, num=3):
     while num:
         yield decimaltimestamp()
         num -= 1
         sleep(0.00001)
Ejemplo n.º 14
0
 def __init__(self, timestamp=None, **kwargs):
     kwargs['timestamp'] = timestamp or decimaltimestamp()
     super(EventWithTimestamp, self).__init__(**kwargs)
Ejemplo n.º 15
0
 def __init__(self, timestamp: Optional[Decimal] = None, **kwargs: Any):
     kwargs["timestamp"] = timestamp or decimaltimestamp()
     super(EventWithTimestamp, self).__init__(**kwargs)
Ejemplo n.º 16
0
    def test_entity_lifecycle(self):
        log_name = uuid4()
        log = self.log_repo.get_or_create(log_name=log_name,
                                          bucket_size='year')
        log = self.log_repo[log_name]
        self.assertIsInstance(log, Timebucketedlog)
        self.assertEqual(log.name, log_name)
        self.assertEqual(log.bucket_size, 'year')

        # Append some messages to the log.
        message1 = 'This is message 1'
        message2 = 'This is message 2'
        message3 = 'This is message 3'
        message4 = 'This is message 4'
        message5 = 'This is message 5'
        message6 = 'This is message 6'
        event1 = log.append_message(message1)
        event2 = log.append_message(message2)
        event3 = log.append_message(message3)
        halfway = decimaltimestamp()
        event4 = log.append_message(message4)
        event5 = log.append_message(message5)
        event6 = log.append_message(message6)

        # Read messages from the log.
        reader = TimebucketedlogReader(log, event_store=self.log_event_store)
        messages = list(reader.get_messages(is_ascending=False))
        self.assertEqual(len(messages), 6)
        self.assertEqual(messages[0], message6)
        self.assertEqual(messages[1], message5)
        self.assertEqual(messages[2], message4)
        self.assertEqual(messages[3], message3)
        self.assertEqual(messages[4], message2)
        self.assertEqual(messages[5], message1)

        # Check we can get all the messages (query running in ascending order).
        messages = list(reader.get_messages(is_ascending=True))
        self.assertEqual(len(messages), 6)
        self.assertEqual(messages[0], message1)
        self.assertEqual(messages[1], message2)
        self.assertEqual(messages[2], message3)
        self.assertEqual(messages[3], message4)
        self.assertEqual(messages[4], message5)
        self.assertEqual(messages[5], message6)

        # Check we can get messages after halfway (query running in descending order).
        messages = list(reader.get_messages(gt=halfway, is_ascending=False))
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0], message6)
        self.assertEqual(messages[1], message5)
        self.assertEqual(messages[2], message4)

        # Check we can get messages until halfway (query running in descending order).
        messages = list(reader.get_messages(lte=halfway, is_ascending=False))
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0], message3)
        self.assertEqual(messages[1], message2)
        self.assertEqual(messages[2], message1)

        # Check we can get messages until halfway (query running in ascending order).
        messages = list(reader.get_messages(lte=halfway, is_ascending=True))
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0], message1)
        self.assertEqual(messages[1], message2)
        self.assertEqual(messages[2], message3)

        # Check we can get messages after halfway (query running in ascending order).
        messages = list(reader.get_messages(gt=halfway, is_ascending=True))
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0], message4)
        self.assertEqual(messages[1], message5)
        self.assertEqual(messages[2], message6)

        # Check we can get last three messages (query running in descending order).
        messages = list(reader.get_messages(limit=3, is_ascending=False))
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0], message6)
        self.assertEqual(messages[1], message5)
        self.assertEqual(messages[2], message4)

        # Check we can get first three messages (query running in ascending order).
        messages = list(reader.get_messages(limit=3, is_ascending=True))
        self.assertEqual(len(messages), 3)
        self.assertEqual(messages[0], message1)
        self.assertEqual(messages[1], message2)
        self.assertEqual(messages[2], message3)

        # Check we can get last line (query running in descending order).
        messages = list(
            reader.get_messages(limit=1, gt=halfway, is_ascending=False))
        self.assertEqual(len(messages), 1)
        self.assertEqual(messages[0], message6)

        # Check we can get the first line after halfway (query running in ascending order).
        messages = list(
            reader.get_messages(limit=1, gt=halfway, is_ascending=True))
        self.assertEqual(len(messages), 1)
        self.assertEqual(messages[0], message4)

        # Check we can get the first line before halfway (query running in descending order).
        messages = list(
            reader.get_messages(limit=1, lte=halfway, is_ascending=False))
        self.assertEqual(len(messages), 1)
        self.assertEqual(messages[0], message3)

        # Check we can get the first line (query running in ascending order).
        messages = list(
            reader.get_messages(limit=1, lte=halfway, is_ascending=True))
        self.assertEqual(len(messages), 1)
        self.assertEqual(messages[0], message1)

        # Check there isn't a line after the last line (query running in ascending order).
        messages = list(
            reader.get_messages(limit=1,
                                gt=event6.timestamp,
                                is_ascending=True))
        self.assertEqual(len(messages), 0)

        # Check there is nothing somehow both after and until halfway.
        messages = list(reader.get_messages(gt=halfway, lte=halfway))
        self.assertEqual(len(messages), 0)
Ejemplo n.º 17
0
    def test_buckets_of_all_sizes(self):
        # Start new second sized log.
        log_id2 = uuid4()
        log = start_new_timebucketedlog(name=log_id2, bucket_size='second')
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new minute sized log.
        log_id3 = uuid4()
        log = start_new_timebucketedlog(name=log_id3, bucket_size='minute')
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new hour sized log.
        log_id4 = uuid4()
        log = start_new_timebucketedlog(name=log_id4, bucket_size='hour')
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new day sized log.
        log_id5 = uuid4()
        log = start_new_timebucketedlog(name=log_id5, bucket_size='day')
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new month sized log.
        log_id6 = uuid4()
        log = start_new_timebucketedlog(name=log_id6, bucket_size='month')
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new year sized log.
        log_id7 = uuid4()
        log = start_new_timebucketedlog(name=log_id7, bucket_size='year')
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new default sized log.
        log_id8 = uuid4()
        log = start_new_timebucketedlog(name=log_id8)
        log.append_message('message')

        # Get the messages.
        reader = TimebucketedlogReader(log, self.log_event_store)
        self.assertTrue(len(list(reader.get_messages())))

        # Start new invalid sized log.
        with self.assertRaises(ValueError):
            log_id9 = uuid4()
            log = start_new_timebucketedlog(name=log_id9,
                                            bucket_size='invalid')

        # Check the helper methods are protected against invalid bucket sizes.
        with self.assertRaises(ValueError):
            log_id10 = uuid4()
            make_timebucket_id(log_id10,
                               decimaltimestamp(),
                               bucket_size='invalid')

        with self.assertRaises(ValueError):
            bucket_starts(decimaltimestamp(), bucket_size='invalid')

        with self.assertRaises(ValueError):
            bucket_duration(bucket_size='invalid')