Files
VoxPopuli/src/consumers/user_consumer.py
2026-05-06 11:13:23 -06:00

132 lines
4.9 KiB
Python

"""User RabbitMQ Consumer - Processes user events and saves to database"""
import sys
import os
import logging
from datetime import datetime
# Add src to path to import modules
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from infrastructure.adapters.rabbitmq.consumer import RabbitMQConsumer
from infrastructure.adapters.rabbitmq.messages import UserMessage, UserEventType
from infrastructure.adapters.persistence.user_repository_sql import UserRepositorySQL
from domain.users import User
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class UserConsumer:
"""Consumer for user events from RabbitMQ"""
def __init__(self):
self.repo = UserRepositorySQL()
self.consumer = RabbitMQConsumer(queue_name='users_queue')
self.consumer.set_callback(self.process_message)
def process_message(self, message_dict: dict):
"""
Processes a user event message from RabbitMQ
Args:
message_dict: Dictionary containing the message data
"""
# Reconstruct the UserMessage object — let exceptions propagate so the
# consumer's callback_wrapper can decide whether to ack, nack+discard, or requeue.
message = UserMessage.from_dict(message_dict)
if message.event_type == UserEventType.CREATE:
self._handle_create_user(message)
elif message.event_type == UserEventType.UPDATE:
self._handle_update_user(message)
elif message.event_type == UserEventType.DELETE:
self._handle_delete_user(message)
else:
logger.warning(f"Unknown event type: {message.event_type}")
def _handle_create_user(self, message: UserMessage):
"""Handle user create event"""
logger.info(f"Creating user: {message.email}")
if not message.fecha_nacimiento:
raise ValueError(f"Missing fecha_nacimiento in CREATE message for email {message.email}")
if not message.fecha_creacion:
raise ValueError(f"Missing fecha_creacion in CREATE message for email {message.email}")
fecha_nacimiento = datetime.fromisoformat(message.fecha_nacimiento)
fecha_creacion = datetime.fromisoformat(message.fecha_creacion)
user = User(
user_id=0, # Will be auto-generated by DB
nombre=message.nombre,
apellido=message.apellido,
email=message.email,
contraseña_hash=message.contraseña_hash,
fecha_nacimiento=fecha_nacimiento,
fecha_creacion=fecha_creacion,
calificacion=message.calificacion,
numero_reportes=message.numero_reportes,
url_foto_perfil=message.url_foto_perfil,
biografia=message.biografia
)
saved_user = self.repo.save(user)
logger.info(f"User created successfully: {saved_user.user_id} - {saved_user.email}")
def _handle_update_user(self, message: UserMessage):
"""Handle user update event"""
logger.info(f"Updating user: {message.user_id}")
user = self.repo.find_by_id(message.user_id)
if not user:
logger.warning(f"User not found: {message.user_id}")
return
if message.nombre:
user.nombre = message.nombre
if message.apellido:
user.apellido = message.apellido
if message.url_foto_perfil is not None:
user.url_foto_perfil = message.url_foto_perfil
if message.biografia is not None:
user.biografia = message.biografia
self.repo.update(user)
logger.info(f"User updated successfully: {message.user_id}")
def _handle_delete_user(self, message: UserMessage):
"""Handle user delete event"""
logger.info(f"Deleting user: {message.user_id}")
success = self.repo.delete(message.user_id)
if success:
logger.info(f"User deleted successfully: {message.user_id}")
else:
logger.warning(f"Failed to delete user: {message.user_id}")
def start(self):
"""Start consuming messages"""
logger.info("Starting User Consumer...")
logger.info("[*] Waiting for user events. Ctrl+C to exit.")
try:
self.consumer.start_consuming()
except KeyboardInterrupt:
logger.info("User Consumer stopped by user")
except Exception as e:
logger.error(f"Consumer error: {e}", exc_info=True)
raise
finally:
if self.repo.db:
try:
self.repo.db.close()
except Exception as e:
logger.error(f"Error closing database session: {e}")
if __name__ == '__main__':
consumer = UserConsumer()
consumer.start()