Beispiel #1
0
def bucket_starts(timestamp, bucket_size):
    dt = datetime_from_timestamp(timestamp)
    assert isinstance(dt, datetime.datetime)
    if bucket_size.startswith('year'):
        return datetime.datetime(dt.year, 1, 1, tzinfo=utc_timezone)
    elif bucket_size.startswith('month'):
        return datetime.datetime(dt.year, dt.month, 1, tzinfo=utc_timezone)
    elif bucket_size.startswith('day'):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 tzinfo=utc_timezone)
    elif bucket_size.startswith('hour'):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 dt.hour,
                                 tzinfo=utc_timezone)
    elif bucket_size.startswith('minute'):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 dt.hour,
                                 dt.minute,
                                 tzinfo=utc_timezone)
    elif bucket_size.startswith('second'):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 dt.hour,
                                 dt.minute,
                                 dt.second,
                                 tzinfo=utc_timezone)
    else:
        raise ValueError("Bucket size not supported: {}".format(bucket_size))
Beispiel #2
0
 def mutate(self, ticket: "Ticket"):
     ticket.history.append(
         TicketFieldUpdated(
             field="name",
             old_value=ticket.name,
             new_value=self.name,
             timestamp=datetime_from_timestamp(self.timestamp),
         ))
     ticket.name = self.name
Beispiel #3
0
        def mutate(self, ticket: "Ticket"):
            ticket.history.append(
                TicketFieldUpdated(
                    field="description",
                    old_value=ticket.description,
                    new_value=self.description,
                    timestamp=datetime_from_timestamp(self.timestamp),
                ))

            ticket.description = self.description
Beispiel #4
0
        def mutate(self, ticket: "Ticket"):
            # TODO: Investigate if there's a way to dependency inject this rather than reaching for the global app
            from project.application.tickets import get_application

            tickets_app = get_application()
            original_ticket = tickets_app.get_ticket(
                id=self.original_ticket_id, at=self.original_ticket_version)
            assert original_ticket is not None
            ticket.name = f"CLONED - {original_ticket.name}"
            ticket.description = original_ticket.description
            # When cloning a ticket, we decide not to copy the previous history but instead start fresh
            ticket.history = [
                TicketCloned(
                    original_ticket_id=self.original_ticket_id,
                    original_ticket_name=original_ticket.name,
                    timestamp=datetime_from_timestamp(self.timestamp),
                )
            ]
Beispiel #5
0
def make_timebucket_id(log_id, timestamp, bucket_size):
    d = datetime_from_timestamp(timestamp)

    assert isinstance(d, datetime.datetime)
    if bucket_size.startswith('year'):
        boundary = '{:04}'.format(d.year)
    elif bucket_size.startswith('month'):
        boundary = '{:04}-{:02}'.format(d.year, d.month)
    elif bucket_size.startswith('day'):
        boundary = '{:04}-{:02}-{:02}'.format(d.year, d.month, d.day)
    elif bucket_size.startswith('hour'):
        boundary = '{:04}-{:02}-{:02}_{:02}'.format(d.year, d.month, d.day,
                                                    d.hour)
    elif bucket_size.startswith('minute'):
        boundary = '{:04}-{:02}-{:02}_{:02}-{:02}'.format(
            d.year, d.month, d.day, d.hour, d.minute)
    elif bucket_size.startswith('second'):
        boundary = '{:04}-{:02}-{:02}_{:02}-{:02}-{:02}'.format(
            d.year, d.month, d.day, d.hour, d.minute, d.second)
    else:
        raise ValueError("Bucket size not supported: {}".format(bucket_size))
    return uuid5(Namespace_Timebuckets, log_id.hex + '_' + boundary)
Beispiel #6
0
def make_timebucket_id(log_id: UUID, timestamp: Union[Decimal, float],
                       bucket_size: str) -> UUID:
    d = datetime_from_timestamp(timestamp)

    assert isinstance(d, datetime.datetime)
    if bucket_size.startswith("year"):
        boundary = "{:04}".format(d.year)
    elif bucket_size.startswith("month"):
        boundary = "{:04}-{:02}".format(d.year, d.month)
    elif bucket_size.startswith("day"):
        boundary = "{:04}-{:02}-{:02}".format(d.year, d.month, d.day)
    elif bucket_size.startswith("hour"):
        boundary = "{:04}-{:02}-{:02}_{:02}".format(d.year, d.month, d.day,
                                                    d.hour)
    elif bucket_size.startswith("minute"):
        boundary = "{:04}-{:02}-{:02}_{:02}-{:02}".format(
            d.year, d.month, d.day, d.hour, d.minute)
    elif bucket_size.startswith("second"):
        boundary = "{:04}-{:02}-{:02}_{:02}-{:02}-{:02}".format(
            d.year, d.month, d.day, d.hour, d.minute, d.second)
    else:
        raise ValueError("Bucket size not supported: {}".format(bucket_size))
    return uuid5(Namespace_Timebuckets, log_id.hex + "_" + boundary)
Beispiel #7
0
def bucket_starts(timestamp: float, bucket_size: str) -> datetime.datetime:
    dt = datetime_from_timestamp(timestamp)
    assert isinstance(dt, datetime.datetime)
    if bucket_size.startswith("year"):
        return datetime.datetime(dt.year, 1, 1, tzinfo=utc_timezone)
    elif bucket_size.startswith("month"):
        return datetime.datetime(dt.year, dt.month, 1, tzinfo=utc_timezone)
    elif bucket_size.startswith("day"):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 tzinfo=utc_timezone)
    elif bucket_size.startswith("hour"):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 dt.hour,
                                 tzinfo=utc_timezone)
    elif bucket_size.startswith("minute"):
        return datetime.datetime(dt.year,
                                 dt.month,
                                 dt.day,
                                 dt.hour,
                                 dt.minute,
                                 tzinfo=utc_timezone)
    elif bucket_size.startswith("second"):
        return datetime.datetime(
            dt.year,
            dt.month,
            dt.day,
            dt.hour,
            dt.minute,
            dt.second,
            tzinfo=utc_timezone,
        )
    else:
        raise ValueError("Bucket size not supported: {}".format(bucket_size))
Beispiel #8
0
 def updated_at(self) -> datetime:
     return datetime_from_timestamp(self.___last_modified__)
Beispiel #9
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)