127 lines
5.2 KiB
Python
127 lines
5.2 KiB
Python
import logging
|
|
import logging.config
|
|
import os
|
|
import asyncio
|
|
from asyncio import Future
|
|
from threading import Thread
|
|
from typing import Optional
|
|
|
|
from aio_pika.abc import AbstractRobustExchange
|
|
|
|
from amqp.adapter.backpressure_handler import BackpressureHandler
|
|
from amqp.adapter.data_message_factory import DataMessageFactory
|
|
from amqp.adapter.amq_route_factory import AMQRouteFactory
|
|
from amqp.adapter.logging_utils import logging_info, logging_warning
|
|
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=None):
|
|
logging.info("***********************************************")
|
|
logging.info("********** AMQ Service *******************")
|
|
logging.info("***********************************************")
|
|
self.loop = asyncio.new_event_loop()
|
|
|
|
self.amq_configuration = amq_configuration
|
|
self.service_adapter = service_adapter
|
|
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.backpressure_thread: Optional[Thread] = None
|
|
|
|
def run(self):
|
|
# self.init(loop) will initialize RabbitMQ connection
|
|
asyncio.set_event_loop(self.loop)
|
|
self.loop.run_until_complete(self.init(self.loop, self.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
|
|
)
|
|
backpressure_handler = BackpressureHandler(
|
|
channel=self.rabbit_mq_client.channel, loop=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,
|
|
backpressure_handler=backpressure_handler,
|
|
)
|
|
await self.register_routes()
|
|
await self.rabbit_mq_client.request_routes()
|
|
self.backpressure_thread = backpressure_handler.start_backpressure_monitor()
|
|
|
|
def cleanup(self):
|
|
logging_info("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_warning(
|
|
"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)
|