import logging import logging.config import os import asyncio from asyncio import Future from aio_pika.abc import AbstractRobustExchange from amqp.adapter.data_message_factory import DataMessageFactory from amqp.adapter.amq_route_factory import AMQRouteFactory from amqp.adapter.service_message_factory import ServiceMessageFactory from amqp.config.amq_configuration import AMQConfiguration from amqp.model.model import DataMessage from amqp.rabbitmq.rabbit_mq_client import RabbitMQClient from amqp.service.amq_message_handler import DataMessageHandler from amqp.service.tracing import initialize_trace logging.basicConfig(level=logging.DEBUG) logging.info(f"CWD = {os.getcwd()}") logging_conf_path = os.path.join(os.getcwd(), "amqp", "service", "logging.conf") if os.path.exists(logging_conf_path): logging.config.fileConfig(logging_conf_path) else: logging_conf_path = os.path.join(os.getcwd(), "logging.conf") if os.path.exists(logging_conf_path): logging.config.fileConfig(logging_conf_path) class AMQService: CLEVER_AMQP_CLIENT_VERSION = os.getenv("CLEVER_AMQP_CLIENT_VERSION") MAX_WAIT = 300 # defaults to 5 minutes (300 seconds) def __init__(self, amq_configuration: AMQConfiguration, service_adapter): logging.info("***********************************************") logging.info("********** AMQ Service *******************") logging.info("***********************************************") self.loop = asyncio.get_event_loop() self.amq_configuration = amq_configuration self.data_message_factory = DataMessageFactory.get_instance( self.amq_configuration.amq_adapter.generator_id ) self.rabbit_mq_client = RabbitMQClient(self.amq_configuration) self.tracer = initialize_trace(name=amq_configuration.amq_adapter.service_name) self.amq_data_message_handler = None self.service_message_factory = ServiceMessageFactory( self.amq_configuration.amq_adapter.service_name ) # self.init(loop) will initialize RabbitMQ connection self.loop.run_until_complete(self.init(self.loop, service_adapter)) logging.info("***********************************************") logging.info("****** AMQ Service Init Complete *********") logging.info("***********************************************") self.loop.run_forever() async def init(self, loop, service_adapter): _reply_to_exchange: AbstractRobustExchange = await self.rabbit_mq_client.init( loop ) self.amq_data_message_handler = DataMessageHandler( service_adapter, self.tracer, self.data_message_factory, self.service_message_factory, _reply_to_exchange, self.rabbit_mq_client, self.amq_configuration, loop=loop, ) await self.register_routes() await self.rabbit_mq_client.request_routes() def cleanup(self): logging.info(" [DBG] AMQService.cleanup() rmqc=%s", self.rabbit_mq_client) if self.rabbit_mq_client: self.rabbit_mq_client.cleanup() async def reinitialize_if_disconnected(self): if not self.rabbit_mq_client.channel or self.rabbit_mq_client.channel.is_closed: self.rabbit_mq_client = RabbitMQClient(self.amq_configuration) await self.rabbit_mq_client.init(loop=self.loop) await self.register_routes() await self.rabbit_mq_client.request_routes() async def register_routes(self) -> AbstractRobustExchange | None: route_mapping = self.amq_configuration.amq_adapter.route_mapping if AMQRouteFactory.validate(route_mapping): try: await self.rabbit_mq_client.register_inbound_routes( route_mapping, self.amq_data_message_handler.inbound_data_message_callback, ) return await self.rabbit_mq_client.register_data_reply_callback( self.amq_data_message_handler.reply_received_callback ) except Exception as e: raise RuntimeError(e) elif route_mapping: logging.info( " [W] route [%s] failed validation, no routes were registered.", route_mapping, ) return None def send_message(self, message: DataMessage, future: Future): self.amq_data_message_handler.outstanding[str(message.id)] = future def remove_outstanding_future(self, message_id: str): self.amq_data_message_handler.outstanding.pop(message_id, None)