Fix bugs issues
This commit is contained in:
@@ -16,8 +16,7 @@ from app.core.config import settings
|
||||
from app.models.users import User, UserSession
|
||||
from app.schemas.auth import UserRegistration, UserLogin, TokenResponse, UserResponse
|
||||
from app.core.security import security_manager
|
||||
from app.services.messaging import message_publisher
|
||||
from shared.messaging.events import UserRegisteredEvent, UserLoginEvent
|
||||
from app.services.messaging import publish_user_registered, publish_user_login
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -58,20 +57,18 @@ class AuthService:
|
||||
await db.commit()
|
||||
await db.refresh(user)
|
||||
|
||||
# Publish user registered event
|
||||
await message_publisher.publish_event(
|
||||
"user_events",
|
||||
"user.registered",
|
||||
UserRegisteredEvent(
|
||||
service_name="auth-service",
|
||||
data={
|
||||
"user_id": str(user.id),
|
||||
"email": user.email,
|
||||
"full_name": user.full_name,
|
||||
"language": user.language
|
||||
}
|
||||
).__dict__
|
||||
)
|
||||
# Publish user registered event - SIMPLIFIED
|
||||
event_data = {
|
||||
"user_id": str(user.id),
|
||||
"email": user.email,
|
||||
"full_name": user.full_name,
|
||||
"language": user.language,
|
||||
"timestamp": datetime.now(timezone.utc).isoformat()
|
||||
}
|
||||
|
||||
success = await publish_user_registered(event_data)
|
||||
if not success:
|
||||
logger.warning("Failed to publish user registered event", user_id=str(user.id))
|
||||
|
||||
logger.info(f"User registered: {user.email}")
|
||||
return UserResponse(**user.to_dict())
|
||||
@@ -144,22 +141,20 @@ class AuthService:
|
||||
db.add(session)
|
||||
await db.commit()
|
||||
|
||||
# Publish login event
|
||||
await message_publisher.publish_event(
|
||||
"user_events",
|
||||
"user.login",
|
||||
UserLoginEvent(
|
||||
service_name="auth-service",
|
||||
data={
|
||||
"user_id": str(user.id),
|
||||
"email": user.email,
|
||||
"ip_address": ip_address,
|
||||
"user_agent": user_agent
|
||||
}
|
||||
).__dict__
|
||||
)
|
||||
# Publish login event - SIMPLIFIED
|
||||
event_data = {
|
||||
"user_id": str(user.id),
|
||||
"email": user.email,
|
||||
"ip_address": ip_address,
|
||||
"user_agent": user_agent,
|
||||
"timestamp": datetime.now(timezone.utc).isoformat()
|
||||
}
|
||||
|
||||
logger.info(f"User login successful: {user.email}")
|
||||
success = await publish_user_login(event_data)
|
||||
if not success:
|
||||
logger.warning("Failed to publish login event", user_id=str(user.id))
|
||||
|
||||
logger.info("User login successful", user_id=str(user.id), email=user.email)
|
||||
|
||||
return TokenResponse(
|
||||
access_token=access_token,
|
||||
|
||||
@@ -2,24 +2,37 @@
|
||||
"""
|
||||
Messaging service for auth service
|
||||
"""
|
||||
|
||||
from shared.messaging.rabbitmq import RabbitMQClient
|
||||
from app.core.config import settings
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Global message publisher
|
||||
message_publisher = RabbitMQClient(settings.RABBITMQ_URL)
|
||||
# Single global instance
|
||||
auth_publisher = RabbitMQClient(settings.RABBITMQ_URL, "auth-service")
|
||||
|
||||
async def setup_messaging():
|
||||
"""Establishes connection to RabbitMQ for the message publisher."""
|
||||
logger.info("Attempting to connect to RabbitMQ...")
|
||||
await message_publisher.connect()
|
||||
logger.info("RabbitMQ connection established.")
|
||||
"""Initialize messaging for auth service"""
|
||||
success = await auth_publisher.connect()
|
||||
if success:
|
||||
logger.info("Auth service messaging initialized")
|
||||
else:
|
||||
logger.warning("Auth service messaging failed to initialize")
|
||||
|
||||
async def cleanup_messaging():
|
||||
"""Closes the connection to RabbitMQ for the message publisher."""
|
||||
logger.info("Attempting to disconnect from RabbitMQ...")
|
||||
await message_publisher.disconnect()
|
||||
logger.info("RabbitMQ connection closed.")
|
||||
"""Cleanup messaging for auth service"""
|
||||
await auth_publisher.disconnect()
|
||||
logger.info("Auth service messaging cleaned up")
|
||||
|
||||
# Convenience functions for auth-specific events
|
||||
async def publish_user_registered(user_data: dict) -> bool:
|
||||
"""Publish user registered event"""
|
||||
return await auth_publisher.publish_user_event("registered", user_data)
|
||||
|
||||
async def publish_user_login(user_data: dict) -> bool:
|
||||
"""Publish user login event"""
|
||||
return await auth_publisher.publish_user_event("login", user_data)
|
||||
|
||||
async def publish_user_logout(user_data: dict) -> bool:
|
||||
"""Publish user logout event"""
|
||||
return await auth_publisher.publish_user_event("logout", user_data)
|
||||
|
||||
@@ -1,168 +1,42 @@
|
||||
# ================================================================
|
||||
# services/data/app/services/messaging.py
|
||||
# ================================================================
|
||||
"""Message queue service for data events"""
|
||||
|
||||
import json
|
||||
import asyncio
|
||||
from typing import Dict, Any, Optional
|
||||
import structlog
|
||||
|
||||
try:
|
||||
from aio_pika import connect_robust, Message, ExchangeType
|
||||
AIO_PIKA_AVAILABLE = True
|
||||
except ImportError:
|
||||
AIO_PIKA_AVAILABLE = False
|
||||
|
||||
from shared.messaging.rabbitmq import RabbitMQClient
|
||||
from app.core.config import settings
|
||||
import logging
|
||||
|
||||
logger = structlog.get_logger()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class DataEventPublisher:
|
||||
"""
|
||||
Event publisher for data service events.
|
||||
Falls back gracefully if RabbitMQ is not available.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.connection = None
|
||||
self.channel = None
|
||||
self.exchange = None
|
||||
self.connected = False
|
||||
|
||||
async def connect(self):
|
||||
"""Connect to RabbitMQ"""
|
||||
if not AIO_PIKA_AVAILABLE:
|
||||
logger.warning("aio-pika not available, messaging disabled")
|
||||
return
|
||||
|
||||
try:
|
||||
self.connection = await connect_robust(settings.RABBITMQ_URL)
|
||||
self.channel = await self.connection.channel()
|
||||
|
||||
# Declare exchange for data events
|
||||
self.exchange = await self.channel.declare_exchange(
|
||||
"data.events",
|
||||
ExchangeType.TOPIC,
|
||||
durable=True
|
||||
)
|
||||
|
||||
self.connected = True
|
||||
logger.info("Connected to RabbitMQ for data events")
|
||||
|
||||
except Exception as e:
|
||||
logger.warning("Failed to connect to RabbitMQ", error=str(e))
|
||||
self.connected = False
|
||||
|
||||
async def disconnect(self):
|
||||
"""Disconnect from RabbitMQ"""
|
||||
if self.connection and not self.connection.is_closed:
|
||||
await self.connection.close()
|
||||
self.connected = False
|
||||
logger.info("Disconnected from RabbitMQ")
|
||||
|
||||
async def publish_data_imported(self, event_data: Dict[str, Any]):
|
||||
"""Publish data imported event"""
|
||||
await self._publish_event("data.imported", event_data)
|
||||
|
||||
async def publish_weather_updated(self, event_data: Dict[str, Any]):
|
||||
"""Publish weather data updated event"""
|
||||
await self._publish_event("weather.updated", event_data)
|
||||
|
||||
async def publish_traffic_updated(self, event_data: Dict[str, Any]):
|
||||
"""Publish traffic data updated event"""
|
||||
await self._publish_event("traffic.updated", event_data)
|
||||
|
||||
async def publish_sales_created(self, event_data: Dict[str, Any]):
|
||||
"""Publish sales record created event"""
|
||||
await self._publish_event("sales.created", event_data)
|
||||
|
||||
async def publish_import_completed(self, event_data: Dict[str, Any]):
|
||||
"""Publish import process completed event"""
|
||||
await self._publish_event("import.completed", event_data)
|
||||
|
||||
async def _publish_event(self, routing_key: str, data: Dict[str, Any]):
|
||||
"""Publish event to exchange"""
|
||||
try:
|
||||
# If not connected, try to connect
|
||||
if not self.connected:
|
||||
await self.connect()
|
||||
|
||||
# If still not connected, log and return
|
||||
if not self.connected:
|
||||
logger.debug("Message not sent - RabbitMQ unavailable", routing_key=routing_key)
|
||||
return
|
||||
|
||||
# Prepare message
|
||||
message_body = json.dumps(data, default=str)
|
||||
message = Message(
|
||||
message_body.encode(),
|
||||
content_type="application/json",
|
||||
delivery_mode=2 # Persistent
|
||||
)
|
||||
|
||||
# Publish to exchange
|
||||
await self.exchange.publish(
|
||||
message,
|
||||
routing_key=routing_key
|
||||
)
|
||||
|
||||
logger.debug("Event published", routing_key=routing_key, data_size=len(message_body))
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to publish event",
|
||||
routing_key=routing_key,
|
||||
error=str(e))
|
||||
# Reset connection on error
|
||||
self.connected = False
|
||||
# Single global instance
|
||||
data_publisher = RabbitMQClient(settings.RABBITMQ_URL, "data-service")
|
||||
|
||||
class MockDataEventPublisher:
|
||||
"""
|
||||
Mock publisher for development/testing when RabbitMQ is not available
|
||||
"""
|
||||
|
||||
async def connect(self):
|
||||
logger.info("Mock publisher - connect called")
|
||||
|
||||
async def disconnect(self):
|
||||
logger.info("Mock publisher - disconnect called")
|
||||
|
||||
async def publish_data_imported(self, event_data: Dict[str, Any]):
|
||||
logger.debug("Mock publish - data imported", event_data=event_data)
|
||||
|
||||
async def publish_weather_updated(self, event_data: Dict[str, Any]):
|
||||
logger.debug("Mock publish - weather updated", event_data=event_data)
|
||||
|
||||
async def publish_traffic_updated(self, event_data: Dict[str, Any]):
|
||||
logger.debug("Mock publish - traffic updated", event_data=event_data)
|
||||
|
||||
async def publish_sales_created(self, event_data: Dict[str, Any]):
|
||||
logger.debug("Mock publish - sales created", event_data=event_data)
|
||||
|
||||
async def publish_import_completed(self, event_data: Dict[str, Any]):
|
||||
logger.debug("Mock publish - import completed", event_data=event_data)
|
||||
async def setup_messaging():
|
||||
"""Initialize messaging for data service"""
|
||||
success = await data_publisher.connect()
|
||||
if success:
|
||||
logger.info("Data service messaging initialized")
|
||||
else:
|
||||
logger.warning("Data service messaging failed to initialize")
|
||||
|
||||
# Global publisher instance
|
||||
# Use mock if RabbitMQ is not available or in development mode
|
||||
if AIO_PIKA_AVAILABLE and hasattr(settings, 'RABBITMQ_URL') and settings.RABBITMQ_URL:
|
||||
data_publisher = DataEventPublisher()
|
||||
else:
|
||||
logger.info("Using mock data publisher")
|
||||
data_publisher = MockDataEventPublisher()
|
||||
|
||||
# Ensure connection is established
|
||||
async def init_messaging():
|
||||
"""Initialize messaging connection"""
|
||||
try:
|
||||
await data_publisher.connect()
|
||||
except Exception as e:
|
||||
logger.warning("Failed to initialize messaging", error=str(e))
|
||||
|
||||
# Cleanup function
|
||||
async def cleanup_messaging():
|
||||
"""Cleanup messaging connection"""
|
||||
try:
|
||||
if hasattr(data_publisher, 'disconnect'):
|
||||
await data_publisher.disconnect()
|
||||
except Exception as e:
|
||||
logger.warning("Failed to cleanup messaging", error=str(e))
|
||||
"""Cleanup messaging for data service"""
|
||||
await data_publisher.disconnect()
|
||||
logger.info("Data service messaging cleaned up")
|
||||
|
||||
# Convenience functions for data-specific events
|
||||
async def publish_data_imported(data: dict) -> bool:
|
||||
"""Publish data imported event"""
|
||||
return await data_publisher.publish_data_event("imported", data)
|
||||
|
||||
async def publish_weather_updated(data: dict) -> bool:
|
||||
"""Publish weather updated event"""
|
||||
return await data_publisher.publish_data_event("weather.updated", data)
|
||||
|
||||
async def publish_traffic_updated(data: dict) -> bool:
|
||||
"""Publish traffic updated event"""
|
||||
return await data_publisher.publish_data_event("traffic.updated", data)
|
||||
|
||||
async def publish_sales_created(data: dict) -> bool:
|
||||
"""Publish sales created event"""
|
||||
return await data_publisher.publish_data_event("sales.created", data)
|
||||
|
||||
@@ -1,9 +1,38 @@
|
||||
"""
|
||||
Messaging service for training service
|
||||
Training service messaging - Uses shared RabbitMQ client only
|
||||
"""
|
||||
|
||||
from shared.messaging.rabbitmq import RabbitMQClient
|
||||
from app.core.config import settings
|
||||
import logging
|
||||
|
||||
# Global message publisher
|
||||
message_publisher = RabbitMQClient(settings.RABBITMQ_URL)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Single global instance
|
||||
training_publisher = RabbitMQClient(settings.RABBITMQ_URL, "training-service")
|
||||
|
||||
async def setup_messaging():
|
||||
"""Initialize messaging for training service"""
|
||||
success = await training_publisher.connect()
|
||||
if success:
|
||||
logger.info("Training service messaging initialized")
|
||||
else:
|
||||
logger.warning("Training service messaging failed to initialize")
|
||||
|
||||
async def cleanup_messaging():
|
||||
"""Cleanup messaging for training service"""
|
||||
await training_publisher.disconnect()
|
||||
logger.info("Training service messaging cleaned up")
|
||||
|
||||
# Convenience functions for training-specific events
|
||||
async def publish_training_started(data: dict) -> bool:
|
||||
"""Publish training started event"""
|
||||
return await training_publisher.publish_training_event("started", data)
|
||||
|
||||
async def publish_training_completed(data: dict) -> bool:
|
||||
"""Publish training completed event"""
|
||||
return await training_publisher.publish_training_event("completed", data)
|
||||
|
||||
async def publish_training_failed(data: dict) -> bool:
|
||||
"""Publish training failed event"""
|
||||
return await training_publisher.publish_training_event("failed", data)
|
||||
|
||||
Reference in New Issue
Block a user