All checks were successful
Build and Deploy Docker Image / build-and-push (push) Successful in 3m56s
-- added automativ queue reconenction (querying for queues to join from server)
99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
import os
|
|
from typing import Optional
|
|
|
|
import aio_pika
|
|
from aio_pika.abc import (
|
|
AbstractChannel,
|
|
AbstractRobustConnection,
|
|
)
|
|
from connections.keycloak import (
|
|
get_valid_access_token,
|
|
)
|
|
from connections.local_files import (
|
|
load_client_info,
|
|
)
|
|
|
|
|
|
class RabbitMQManager:
|
|
"""Singleton manager for RabbitMQ connection and channels."""
|
|
|
|
_instance: Optional["RabbitMQManager"] = None
|
|
_connection: Optional[AbstractRobustConnection] = None
|
|
_consumer_channel: Optional[AbstractChannel] = None
|
|
_publisher_channel: Optional[AbstractChannel] = None
|
|
_heartbeat_channel: Optional[AbstractChannel] = None
|
|
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super().__new__(cls)
|
|
return cls._instance
|
|
|
|
async def connect(self):
|
|
"""Establish the main connection if not already connected."""
|
|
client_info = load_client_info()
|
|
if not client_info:
|
|
return None
|
|
access_token = get_valid_access_token()
|
|
if not access_token:
|
|
return None
|
|
if self._connection is None or self._connection.is_closed:
|
|
print("Creating new RabbitMQ connection...")
|
|
self._connection = await aio_pika.connect_robust(
|
|
host=os.environ["RABBITMQ_HOST"],
|
|
port=int(os.environ["RABBITMQ_PORT"]),
|
|
login=str(client_info["system_id"]),
|
|
password=access_token,
|
|
virtualhost="/",
|
|
)
|
|
print("RabbitMQ connection established")
|
|
return self._connection
|
|
|
|
async def get_consumer_channel(self):
|
|
"""Get channel for consuming messages."""
|
|
if self._connection:
|
|
if self._consumer_channel is None or self._consumer_channel.is_closed:
|
|
self._consumer_channel = await self._connection.channel()
|
|
await self._consumer_channel.set_qos(prefetch_count=1, global_=True)
|
|
print("Consumer channel created")
|
|
return self._consumer_channel
|
|
return self._consumer_channel
|
|
return None
|
|
|
|
async def get_publisher_channel(self):
|
|
"""Get channel for publishing regular messages."""
|
|
if self._connection:
|
|
if self._publisher_channel is None or self._publisher_channel.is_closed:
|
|
self._publisher_channel = await self._connection.channel()
|
|
print("Publisher channel created")
|
|
return self._publisher_channel
|
|
return None
|
|
|
|
async def get_heartbeat_channel(self):
|
|
"""Get channel for heartbeat publishing."""
|
|
if self._connection:
|
|
if self._heartbeat_channel is None or self._heartbeat_channel.is_closed:
|
|
self._heartbeat_channel = await self._connection.channel()
|
|
print("Heartbeat channel created")
|
|
return self._heartbeat_channel
|
|
return None
|
|
|
|
async def close(self):
|
|
"""Close all channels and the main connection gracefully."""
|
|
print("Closing RabbitMQ channels and connection...")
|
|
|
|
for channel in [
|
|
self._consumer_channel,
|
|
self._publisher_channel,
|
|
self._heartbeat_channel,
|
|
]:
|
|
if channel and not channel.is_closed:
|
|
await channel.close()
|
|
|
|
if self._connection and not self._connection.is_closed:
|
|
await self._connection.close()
|
|
print("RabbitMQ connection closed")
|
|
|
|
|
|
# Create global singleton instance
|
|
rabbitmq_manager = RabbitMQManager()
|