Files
amq-adapter-python/amqp/model/model.py
T
2025-02-20 15:45:26 +08:00

108 lines
2.8 KiB
Python

import base64
from typing import List, Mapping, Dict
from dataclasses import dataclass, field
from enum import Enum, auto
from amqp.model.snowflake_id import SnowflakeId
from amqp.router.utils import sanitize_as_rabbitmq_name
RS = ":"
@dataclass(frozen=True)
class AMQRoute:
"""
Configuration item representing one AMQRoute. Adapter uses this to declare the Exchange
and/or queue and bind the key as routing expression.
:param componentName: a service/component name that this route points to (owner of the route)
:param exchange: RabbitMQ exchange name
:param queue: RabbitMQ queue name
:param key: RabbitMQ TOPIC Exchange routing key
:param timeout: Timeout in milliseconds, how long to wait for reply, or not waiting if less then 1
:param validUntil: optional timestamp (millis from epoch) after which the route is ignored
"""
componentName: str
exchange: str
queue: str
key: str
timeout: int
validUntil: int
FORMAT = "Component-Name:Exchange-Name:Queue-Name:Routing-Key:Timeout:Valid-Until"
def __str__(self):
return (
f"{self.componentName}{RS}{self.exchange}{RS}{self.queue}{RS}{self.key}"
f"{RS}{self.timeout}{RS}{self.validUntil}"
)
def __eq__(self, other):
if isinstance(other, AMQRoute):
return (self.componentName == other.componentName
and self.queue == other.queue
and self.key == other.key)
return False
@property
def primary_key(self):
return f"{self.componentName}{RS}{self.queue}{RS}{self.key}"
def as_string(self) -> str:
return self.__str__()
@dataclass
class AMQMessage:
magic: str
id: SnowflakeId
method: str
domain: str
path: str
headers: Mapping[str, List[str]]
trace_info: Mapping[str, str]
base64_body: bytes
def routing_key(self) -> str:
return sanitize_as_rabbitmq_name(f"{self.domain}.{self.path}")
def body(self) -> bytes:
return base64.b64decode(self.base64_body)
@dataclass
class AMQResponse:
id: str
response_code: int
content_type: str
response: bytes
error: str
error_cause: str
trace_info: Mapping[str, str]
def body(self) -> bytes:
return base64.b64decode(self.response)
class ServiceMessageType(Enum):
ROUTING_DATA_REQUEST = auto()
ROUTING_DATA = auto()
ROUTING_DATA_REMOVE = auto()
ROUTING_DATA_REPLACE = auto()
UNKNOWN = auto()
@dataclass(frozen=True)
class CleverMicroServiceMessage:
id: SnowflakeId = None
payload_type: int = 0
message_type: ServiceMessageType = ServiceMessageType.UNKNOWN
recipient_name: str = None
reply_to: str = None
trace_info: Dict[str, str] = field(default_factory=dict)
message: str = None
def is_valid(self) -> bool:
return self.message_type is not None