#23 refactor to use shared code between services
Unit test coverage / pytest (pull_request) Failing after 1m9s
Unit test coverage / pytest (push) Failing after 1m11s

This commit is contained in:
Stanislav Hejny
2025-05-11 15:06:39 +01:00
parent 81e9616072
commit 2f6dbd2ad8
26 changed files with 699 additions and 1009 deletions
+2 -6
View File
@@ -40,13 +40,9 @@ class RouteDatabase:
return re.compile(".*")
return re.compile(regex)
def matches(
self, routing_key_from_route: str, routing_key_from_message: str
) -> bool:
def matches(self, routing_key_from_route: str, routing_key_from_message: str) -> bool:
route_pattern = self.pattern(routing_key_from_route)
return bool(
route_pattern.match(sanitize_as_rabbitmq_name(routing_key_from_message))
)
return bool(route_pattern.match(sanitize_as_rabbitmq_name(routing_key_from_message)))
def wrap_routes(self) -> str:
return ",".join(str(route) for route in self.routes)
+6 -16
View File
@@ -27,7 +27,7 @@ class RouterBase:
self.route_removed_notifier: Callable[[AMQRoute], None] | None = None
def get_routing_key(self, message: DataMessage) -> str:
return sanitize_as_rabbitmq_name(f"{message.domain}.{message.path}")
return sanitize_as_rabbitmq_name(f"{message.domain()}.{message.path()}")
def wrap_routes(self) -> str:
return self.route_database.wrap_routes()
@@ -37,10 +37,7 @@ class RouterBase:
def unwrap_route_list(self, route_string: str) -> List[AMQRoute]:
logging_debug("RouterMaster.unwrapRoutes, route(s): %s", route_string)
routes = [
AMQRouteFactory.from_string(route_str)
for route_str in route_string.split(",")
]
routes = [AMQRouteFactory.from_string(route_str) for route_str in route_string.split(",")]
return [route for route in routes if route != NULL_ROUTE]
def get_routes(self) -> Set[AMQRoute]:
@@ -50,14 +47,12 @@ class RouterBase:
return self.route_database.find_route(domain, path)
def find_route_by_message(self, message: DataMessage) -> AMQRoute | None:
return self.route_database.find_route(message.domain, message.path)
return self.route_database.find_route(message.domain(), message.path())
def add_routes(self, message: str) -> None:
try:
amq_route_list = self.unwrap_route_list(message)
logging_info(
" [DBG] RouterMaster.addRoute [%d]: %s", len(amq_route_list), message
)
logging_info(" [DBG] RouterMaster.addRoute [%d]: %s", len(amq_route_list), message)
for route in amq_route_list:
logging_info("RouterMaster.addRoute, adding route: %s", route)
if not route.exchange and not route.queue and not route.key:
@@ -81,14 +76,9 @@ class RouterBase:
def remove_routes(self, message: str) -> None:
try:
to_remove = [
AMQRouteFactory.from_string(route_str)
for route_str in message.split(",")
]
to_remove = [AMQRouteFactory.from_string(route_str) for route_str in message.split(",")]
removed_count = sum(1 for route in to_remove if self.remove_route(route))
logging_info(
f"RouterMaster.removeRoutes(): {message}, removed={removed_count}"
)
logging_info(f"RouterMaster.removeRoutes(): {message}, removed={removed_count}")
except IOError as err:
logging_error(f"Can't remove route(s): {err}")
+8 -24
View File
@@ -77,17 +77,13 @@ class RouterConsumer(RouterProducer):
except Exception as ioe:
logging_error("RouterConsumer FATAL: cannot initialize, %s", ioe)
else:
logging_error(
"RouterConsumer FATAL: cannot initialize, RabbitMQ channel is not open."
)
logging_error("RouterConsumer FATAL: cannot initialize, RabbitMQ channel is not open.")
"""
* ServiceMessageType.ROUTING_DATA_REQUEST handler listening on queue 'CleverMicroRequest'
"""
async def handle_routing_data_request_message(
self, message: AbstractIncomingMessage
):
async def handle_routing_data_request_message(self, message: AbstractIncomingMessage):
# some debug statements, TODO - remove for prod release
delivery_tag = message.delivery_tag
debug = "Delivery.Properties = " + message.properties.__str__()
@@ -101,9 +97,7 @@ class RouterConsumer(RouterProducer):
await message.ack(False)
cm_message: ServiceMessage = self.service_message_factory.from_bytes(
message.body
)
cm_message: ServiceMessage = self.service_message_factory.from_bytes(message.body)
route_mapping: str = self.wrap_own_routes()
logging_debug(
"******[%s] (ROUTING_DATA_REQ) msg=%s, routeMap=[%s]",
@@ -124,9 +118,7 @@ class RouterConsumer(RouterProducer):
route_mapping,
cm_message.reply_to,
)
await self.publish_service_message(
service_message, self.cm_response_exchange
)
await self.publish_service_message(service_message, self.cm_response_exchange)
except Exception as err:
logging_error(
"******[%s] (ROUTING_DATA_REQ) Response to queue: %s failed: %s",
@@ -158,9 +150,7 @@ class RouterConsumer(RouterProducer):
serviceMessage: ServiceMessage = self.service_message_factory.of(
ServiceMessageType.ROUTING_DATA, route.as_string(), ANY_RECIPIENT
)
await self.publish_service_message(
serviceMessage, self.cm_response_exchange
)
await self.publish_service_message(serviceMessage, self.cm_response_exchange)
self.add_own_route(route)
logging_info("RouterConsumer registered Route: %s", route)
else:
@@ -182,9 +172,7 @@ class RouterConsumer(RouterProducer):
service_message: ServiceMessage = self.service_message_factory.of(
ServiceMessageType.ROUTING_DATA_REMOVE, route.as_string(), ANY_RECIPIENT
)
if not await self.publish_service_message(
service_message, self.cm_response_exchange
):
if not await self.publish_service_message(service_message, self.cm_response_exchange):
logging_warning(
"RouterConsumer couldn't remove current route: %s, channel not open.",
route,
@@ -201,13 +189,9 @@ class RouterConsumer(RouterProducer):
* Cleanup - de-register routes with master.
"""
routes: Set[AMQRoute] = self.get_routes()
logging_info(
"RouterConsumer.cleanup() [%d]: %s", len(routes), self.wrap_routes()
)
logging_info("RouterConsumer.cleanup() [%d]: %s", len(routes), self.wrap_routes())
not_removed = sum(
1
for r in (self.remove_route_on_cleanup(route) for route in routes)
if not r
1 for r in (self.remove_route_on_cleanup(route) for route in routes) if not r
)
if not_removed > 0:
logging_warning(
+6 -17
View File
@@ -47,9 +47,7 @@ class RouterProducer(RouterBase):
"""
super().__init__()
self.connection: AbstractRobustConnection | None = None
self.service_message_factory = ServiceMessageFactory(
configuration.amq_adapter.service_name
)
self.service_message_factory = ServiceMessageFactory(configuration.amq_adapter.service_name)
self.amq_configuration: AMQConfiguration = configuration
self.channel: AbstractRobustChannel | None = None
self.cm_request_exchange: AbstractRobustExchange | None = None
@@ -98,9 +96,7 @@ class RouterProducer(RouterBase):
arguments={},
)
# 2b. bind queue to CM_RESPONSE_EXCHANGE w/o any conditions (empty routing key)
await _response_queue.bind(
exchange=CM_RESPONSE_EXCHANGE, routing_key="#"
)
await _response_queue.bind(exchange=CM_RESPONSE_EXCHANGE, routing_key="#")
# 2c. listen for incoming RoutingData messages
_c_tag = await _response_queue.consume(
callback=self.handle_routing_data_message, no_ack=False
@@ -114,9 +110,7 @@ class RouterProducer(RouterBase):
logging_error("RouterProducer FATAL: cannot initialize, %s", ioe)
else:
logging_error(
"RouterProducer FATAL: cannot initialize, RabbitMQ channel is not open."
)
logging_error("RouterProducer FATAL: cannot initialize, RabbitMQ channel is not open.")
async def handle_routing_data_message(self, message: AbstractIncomingMessage):
"""
@@ -130,9 +124,7 @@ class RouterProducer(RouterBase):
message.message_id,
)
await message.ack(multiple=False)
cm_message: ServiceMessage = self.service_message_factory.from_bytes(
message.body
)
cm_message: ServiceMessage = self.service_message_factory.from_bytes(message.body)
# ignore the message if it comes from ourselves (even if from different instance)
logging_debug(
"******[%s] ROUTING_DATA, msg=%s, routeMap=[%s] sn=%s, replyTo=%s",
@@ -144,8 +136,7 @@ class RouterProducer(RouterBase):
)
if (
cm_message.is_valid()
and not self.amq_configuration.amq_adapter.service_name
== cm_message.reply_to
and not self.amq_configuration.amq_adapter.service_name == cm_message.reply_to
):
if cm_message.message_type == ServiceMessageType.ROUTING_DATA:
self.add_routes(cm_message.message)
@@ -164,9 +155,7 @@ class RouterProducer(RouterBase):
serviceMessage: ServiceMessage = self.service_message_factory.of(
ServiceMessageType.ROUTING_DATA_REQUEST, "", ANY_RECIPIENT
)
if not await self.publish_service_message(
serviceMessage, self.cm_request_exchange
):
if not await self.publish_service_message(serviceMessage, self.cm_request_exchange):
logging_warning(
"RouterProducer could not request route data: %s channel is not open.",
CM_REQUEST_EXCHANGE,