"""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()