Files
bakery-ia/shared/clients/notification_client.py
2025-10-24 13:05:04 +02:00

131 lines
4.5 KiB
Python

# shared/clients/notification_client.py
"""
Notification Service Client for Inter-Service Communication
Provides access to notification and email sending from other services
"""
import structlog
from typing import Dict, Any, Optional
from uuid import UUID
from shared.clients.base_service_client import BaseServiceClient
from shared.config.base import BaseServiceSettings
logger = structlog.get_logger()
class NotificationServiceClient(BaseServiceClient):
"""Client for communicating with the Notification Service"""
def __init__(self, config: BaseServiceSettings):
super().__init__("notification", config)
def get_service_base_path(self) -> str:
return "/api/v1/notifications"
# ================================================================
# NOTIFICATION ENDPOINTS
# ================================================================
async def send_notification(
self,
tenant_id: str,
notification_type: str,
message: str,
recipient_email: Optional[str] = None,
subject: Optional[str] = None,
html_content: Optional[str] = None,
priority: str = "normal",
metadata: Optional[Dict[str, Any]] = None
) -> Optional[Dict[str, Any]]:
"""
Send a notification
Args:
tenant_id: Tenant ID (UUID as string)
notification_type: Type of notification (email, sms, push, in_app)
message: Notification message
recipient_email: Recipient email address (for email notifications)
subject: Email subject (for email notifications)
html_content: HTML content for email (optional)
priority: Priority level (low, normal, high, urgent)
metadata: Additional metadata
Returns:
Dictionary with notification details
"""
try:
notification_data = {
"type": notification_type,
"message": message,
"priority": priority,
"recipient_email": recipient_email,
"subject": subject,
"html_content": html_content,
"metadata": metadata or {}
}
result = await self.post("send", data=notification_data, tenant_id=tenant_id)
if result:
logger.info("Notification sent successfully",
tenant_id=tenant_id,
notification_type=notification_type)
return result
except Exception as e:
logger.error("Error sending notification",
error=str(e),
tenant_id=tenant_id,
notification_type=notification_type)
return None
async def send_email(
self,
tenant_id: str,
to_email: str,
subject: str,
message: str,
html_content: Optional[str] = None,
priority: str = "normal"
) -> Optional[Dict[str, Any]]:
"""
Send an email notification (convenience method)
Args:
tenant_id: Tenant ID (UUID as string)
to_email: Recipient email address
subject: Email subject
message: Email message (plain text)
html_content: HTML version of email (optional)
priority: Priority level (low, normal, high, urgent)
Returns:
Dictionary with notification details
"""
return await self.send_notification(
tenant_id=tenant_id,
notification_type="email",
message=message,
recipient_email=to_email,
subject=subject,
html_content=html_content,
priority=priority
)
# ================================================================
# UTILITY METHODS
# ================================================================
async def health_check(self) -> bool:
"""Check if notification service is healthy"""
try:
result = await self.get("../health") # Health endpoint is not tenant-scoped
return result is not None
except Exception as e:
logger.error("Notification service health check failed", error=str(e))
return False
# Factory function for dependency injection
def create_notification_client(config: BaseServiceSettings) -> NotificationServiceClient:
"""Create notification service client instance"""
return NotificationServiceClient(config)