2026-01-26 11:09:40 -05:00

68 lines
2.4 KiB
Python

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