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)
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)
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
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
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()
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=[], )
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