Ejemplo n.º 1
0
 def _try_update_with_unexpected_context(
     self, integration_record: IntegrationRecord
 ):
     epoch = datetime.datetime.utcnow().timestamp()
     item = {
         "TableName": self.table_name,
         "Key": {"trace_id": serialize(integration_record.trace_id)},
         "UpdateExpression": "SET "
         "   contexts_resolutions_unexpected.#context = :context_resolution, "  # noqa: E501
         "   integrations = list_append(integrations, :new_integrations)",
         "ExpressionAttributeNames": {
             "#context": integration_record.context
         },
         "ExpressionAttributeValues": {
             ":context_resolution": serialize(
                 {
                     "context": integration_record.context,
                     "resolution": integration_record.resolve,
                     "error": integration_record.error,
                     "timestamp": epoch,
                 }
             ),
             ":new_integrations": serialize(
                 [record_asdict(integration_record)]
             ),
         },
         # "ConditionExpression": """
         # attribute_exists(trace_id)
         # """
     }
     self.client.update_item(**item)
Ejemplo n.º 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)
Ejemplo n.º 3
0
def record():
    return record_asdict(
        CommandRecord(trace_id='tid',
                      topic='ApplicationCommand',
                      version=1,
                      timestamp=0.0,
                      message=MessageType.APPLICATION_COMMAND.value,
                      payload={}))
Ejemplo n.º 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
Ejemplo n.º 5
0
    def _publish_with_partition_key(self,
                                    messages: SequenceOfInfrastructureMessage):
        entries = [{
            "TableName": self.table_name,
            "Item": {
                "trace_id": serialize(m.__trace_id__),
                "body": serialize(record_asdict(self.mapper.serialize(m))),
            },
        } for m in messages]

        for entry in entries:
            self.client.put_item(**entry)
Ejemplo n.º 6
0
    def _publish(
        self,
        messages: typing.Sequence[InfrastructureMessage],
    ):
        entries = [{
            "stateMachineArn":
            self.state_machine_arn,
            "input":
            json.dumps({
                "publish_at": getattr(m, m.__publish_at_field__),
                "payload": record_asdict(self.mapper.serialize(m)),
            }),
        } for m in messages if isinstance(m, ScheduleIntegartionEvent)]

        for entry in entries:
            self.client.start_execution(**entry)
Ejemplo n.º 7
0
    def _publish_with_partition_key_and_sort_key(
            self, messages: SequenceOfInfrastructureMessage):
        _sort_key = self.sort_key
        if _sort_key is None:
            raise ValueError("sort_key should not be NoneType")

        entries = [{
            "TableName": self.table_name,
            "Item": {
                "trace_id": serialize(m.__trace_id__),
                _sort_key: serialize(getattr(messages, _sort_key)),
                "body": serialize(record_asdict(self.mapper.serialize(m))),
            },
        } for m in messages]

        for entry in entries:
            self.client.put_item(**entry)
Ejemplo n.º 8
0
    def _publish(
        self,
        messages: typing.Sequence[InfrastructureMessage],
    ):
        entries = [{
            "QueueUrl":
            self.queue_url,
            "MessageBody":
            json.dumps(record_asdict(self.mapper.serialize(m))),
        } for m in messages]

        errors = []
        for i, entry in enumerate(entries):
            try:
                self.client.send_message(**entry)
            except Exception as error:  # pylint: disable=broad-except
                errors.append(
                    PublisherError.EntryError(messages[i], str(error)))
        if len(errors) > 0:
            raise PublisherError(errors)
Ejemplo n.º 9
0
    def _publish(
        self,
        messages: typing.Sequence[InfrastructureMessage],
    ):
        entries = [{
            "Source":
            self.context,
            "Detail":
            json.dumps(record_asdict(self.mapper.serialize(m))),
            "DetailType":
            m.__class__.__name__,
            "EventBusName":
            self.bus_name,
        } for m in messages]

        response = self.client.put_events(Entries=entries)
        if response["FailedEntryCount"] > 0:
            errors = [
                PublisherError.EntryError(messages[i], e["ErrorCode"])
                for i, e in enumerate(response["Entries"])
                if "EventId" not in e  # Failed
            ]
            raise PublisherError(errors)
Ejemplo n.º 10
0
    def _publish(
        self,
        messages: typing.Sequence[InfrastructureMessage],
    ):
        entries = [
            {
                "TopicArn": self.topic_arn,
                "MessageAttributes": {
                    "subject": {
                        "DataType": "String",
                        "StringValue": (
                            f"{self.context}:{m.__class__.__name__}"
                        ),
                    },
                    "context": {
                        "DataType": "String",
                        "StringValue": self.context,
                    },
                    "topic": {
                        "DataType": "String",
                        "StringValue": m.__class__.__name__,
                    },
                },
                "Message": json.dumps(record_asdict(self.mapper.serialize(m))),
            }
            for m in messages
        ]

        errors = []
        for i, entry in enumerate(entries):
            try:
                self.client.publish(**entry)
            except Exception as error:  # pylint: disable=broad-except
                errors.append(PublisherError.EntryError(entries[i], error))
        if len(errors) > 0:
            raise PublisherError(errors)