""" Metadata enrichment service for events. Automatically populates domain-appropriate metadata based on entity type. All methods are async-safe, using sync_to_async with proper select_related to avoid lazy loading issues in an async context. """ from typing import Dict, Any, Optional import logging from core.services.metadata.service import SERVICE_EVENTS, enrich_service_domain from core.services.metadata.project import PROJECT_EVENTS, enrich_project_domain from core.services.metadata.account import ACCOUNT_EVENTS, enrich_account_domain from core.services.metadata.customer import CUSTOMER_EVENTS, enrich_customer_domain logger = logging.getLogger(__name__) class MetadataEnricher: """ Enriches event metadata with domain-appropriate fields. All methods handle async context properly by loading entities with select_related in a single sync_to_async call. """ @staticmethod async def enrich( event_type: str, entity_type: str, entity_id: str, existing_metadata: Optional[Dict[str, Any]] = None ) -> Dict[str, Any]: """ Enrich metadata based on the event type and entity. Args: event_type: The EventTypeChoices value entity_type: Type of entity (Service, Project, ServiceSession, etc.) entity_id: UUID of the entity existing_metadata: Any metadata already provided (takes precedence) Returns: Enriched metadata dict (existing values are preserved) """ enriched = {} try: # Determine domain and enrich accordingly if event_type in SERVICE_EVENTS: enriched = await enrich_service_domain(entity_type, entity_id) elif event_type in PROJECT_EVENTS: enriched = await enrich_project_domain(entity_type, entity_id) elif event_type in ACCOUNT_EVENTS: enriched = await enrich_account_domain(entity_type, entity_id) elif event_type in CUSTOMER_EVENTS: enriched = await enrich_customer_domain(entity_type, entity_id) except Exception as e: # Log but don't fail - enrichment is optional logger.warning(f"Metadata enrichment failed for {entity_type}/{entity_id}: {e}") # Merge with existing metadata (existing takes precedence) if existing_metadata: enriched.update(existing_metadata) return enriched