Example #1
0
    def start_trace_segment(
            self, request: InfrastructureMessage) -> TraceSegmentRecorder:
        record = self.mapper.serialize(request)

        subject = record.topic
        if isinstance(record, EventRecord):
            subject = f"{record.context}:{record.topic}"

        trace_segment_id = self._get_trace_segment_id(record.trace_id, subject)

        if trace_segment_id in self.segments:
            raise IdempotencyItemError()

        epoch = datetime.datetime.utcnow().timestamp()
        self.segments[trace_segment_id] = TraceSegment(
            trace_id=record.trace_id,
            topic=record.topic,
            timestamp=epoch,
            timestamp_resolution=None,
            request=record,
            resolution=TraceResolution.Resolutions.pending,
            error=None,
        )

        return TraceSegmentRecorder(request, self)
Example #2
0
    def start_trace_segment(
        self, request: InfrastructureMessage
    ) -> TraceSegmentRecorder:
        record = self.mapper.serialize(request)

        subject = record.topic
        if isinstance(record, EventRecord):
            subject = f"{record.context}:{record.topic}"

        epoch = datetime.datetime.utcnow().timestamp()
        item = {
            "TableName": self.table_name,
            "Item": {
                "trace_id": serialize(record.trace_id),
                "subject": serialize(subject),
                "timestamp": serialize(epoch),
                "timestamp_resolution": serialize(None),
                "request": serialize(record_asdict(record)),
                "resolution": serialize(TraceResolution.Resolutions.pending),
                "error": serialize(None),
            },
            "ConditionExpression": "(attribute_not_exists(trace_id) "
            "and attribute_not_exists(topic)) "
            "or resolution = :failure",
            "ExpressionAttributeValues": {
                ":failure": serialize(TraceResolution.Resolutions.failure)
            },
        }

        try:
            self.client.put_item(**item)
        except self.client.exceptions.ConditionalCheckFailedException as error:
            raise IdempotencyItemError() from error

        return TraceSegmentRecorder(request, self)
Example #3
0
def test_idempotency_already_exists():
    record_manager = mock.MagicMock()
    record_manager.store_in_progress = mock.Mock(
        side_effect=IdempotencyItemError())
    record = {'trace_id': '', 'topic': ''}

    with Idempotency(record, record_manager) as record:
        assert record is None
Example #4
0
    def start_trace(
        self,
        request: typing.Union[
            ApplicationCommand, ApplicationQuery, IntegrationEvent
        ],
    ) -> None:
        try:
            resolvers = getattr(request, "__resolvers__")
        except AttributeError as error:
            raise DefinitionError(
                "request should have __resolvers__: "
                f"{request.__class__.__name__}"
            ) from error

        record = self.mapper.serialize(request)

        epoch = datetime.datetime.utcnow().timestamp()

        epoch_resolution = None
        resolution = TraceResolution.Resolutions.pending
        if len(resolvers) == 0:
            epoch_resolution = epoch
            resolution = TraceResolution.Resolutions.success

        item = {
            "TableName": self.table_name,
            "Item": {
                "trace_id": serialize(record.trace_id),
                "topic": serialize(record.topic),
                "message": serialize(record.message),
                "request": serialize(record_asdict(record)),
                "resolution": serialize(resolution),
                "version": serialize(1),
                "timestamp": serialize(epoch),
                "timestamp_resolution": serialize(epoch_resolution),
                "contexts_resolutions": serialize(
                    {
                        context: {
                            "context": context,
                            "resolution": TraceResolution.Resolutions.pending,
                            "error": None,
                            "timestamp": None,
                        }
                        for context in resolvers
                    }
                ),
                "contexts_resolutions_unexpected": serialize({}),
                "integrations": serialize([]),
            },
            "ConditionExpression": "attribute_not_exists(trace_id)",
        }

        try:
            self.client.put_item(**item)
        except self.client.exceptions.ConditionalCheckFailedException as error:
            raise IdempotencyItemError() from error
Example #5
0
 def store_in_progress(self, record: dict):
     if not self.exists_in_progress_or_success(record["trace_id"],
                                               record["topic"]):
         self.heap.append({
             "trace_id": record["trace_id"],
             "topic": record["topic"],
             "payload": record,
             "status": "progress",
             "error": None,
         })
     else:
         raise IdempotencyItemError()
Example #6
0
    def start_trace(
        self,
        request: typing.Union[ApplicationCommand, ApplicationQuery,
                              IntegrationEvent],
    ) -> None:
        try:
            resolvers = getattr(request, "__resolvers__")
        except AttributeError as error:
            raise DefinitionError("request should have __resolvers__: "
                                  f"{request.__class__.__name__}") from error

        record = typing.cast(
            typing.Union[CommandRecord, QueryRecord],
            self.mapper.serialize(request),
        )

        if record.trace_id in self.traces:
            raise IdempotencyItemError()

        epoch = datetime.datetime.utcnow().timestamp()

        epoch_resolution = None
        resolution = TraceResolution.Resolutions.pending
        if len(resolvers) == 0:
            epoch_resolution = epoch
            resolution = TraceResolution.Resolutions.success

        self.traces[record.trace_id] = Trace(
            trace_id=record.trace_id,
            topic=record.topic,
            message=record.message,
            request=record,
            resolution=resolution,
            version=1,
            timestamp=epoch,
            timestamp_resolution=epoch_resolution,
            contexts_resolutions={
                context: ContextResolution(
                    context=context,
                    resolution=TraceResolution.Resolutions.pending,
                    timestamp=None,
                    error=None,
                )
                for context in resolvers
            },
            contexts_resolutions_unexpected={},
            integrations=[],
        )
Example #7
0
    def store_in_progress(self, record: dict):
        epoch = datetime.datetime.utcnow().timestamp()
        item = {
            "TableName": self.table_name,
            "Item": {
                "trace_id": serialize(record["trace_id"]),
                "timestamp": serialize(epoch),
                "topic": serialize(record["topic"]),
                "payload": serialize(record),
                "status": serialize("progress"),
                "error": serialize(None),
            },
            "ConditionExpression": "(attribute_not_exists(trace_id) "
            "and attribute_not_exists(topic)) "
            "or #status = :failure",
            "ExpressionAttributeNames": {"#status": "status"},
            "ExpressionAttributeValues": {":failure": serialize("failure")},
        }

        try:
            self.client.put_item(**item)
        except self.client.exceptions.ConditionalCheckFailedException as error:
            raise IdempotencyItemError() from error