# services/external/app/core/config.py from shared.config.base import BaseServiceSettings import os from pydantic import Field class DataSettings(BaseServiceSettings): """Data service specific settings""" # Service Identity SERVICE_NAME: str = "external-service" VERSION: str = "1.0.0" APP_NAME: str = "Bakery External Data Service" DESCRIPTION: str = "External data collection service for weather and traffic data" # API Configuration API_V1_STR: str = "/api/v1" # Database configuration (secure approach - build from components) @property def DATABASE_URL(self) -> str: """Build database URL from secure components""" # Try complete URL first (for backward compatibility) complete_url = os.getenv("EXTERNAL_DATABASE_URL") if complete_url: return complete_url # Build from components (secure approach) user = os.getenv("EXTERNAL_DB_USER", "external_user") password = os.getenv("EXTERNAL_DB_PASSWORD", "external_pass123") host = os.getenv("EXTERNAL_DB_HOST", "localhost") port = os.getenv("EXTERNAL_DB_PORT", "5432") name = os.getenv("EXTERNAL_DB_NAME", "external_db") return f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{name}" # External API Configuration AEMET_API_KEY: str = os.getenv("AEMET_API_KEY", "") AEMET_BASE_URL: str = "https://opendata.aemet.es/opendata" AEMET_TIMEOUT: int = int(os.getenv("AEMET_TIMEOUT", "90")) # Increased for unstable API AEMET_RETRY_ATTEMPTS: int = int(os.getenv("AEMET_RETRY_ATTEMPTS", "5")) # More retries for connection issues AEMET_ENABLED: bool = os.getenv("AEMET_ENABLED", "true").lower() == "true" # Allow disabling AEMET MADRID_OPENDATA_API_KEY: str = os.getenv("MADRID_OPENDATA_API_KEY", "") MADRID_OPENDATA_BASE_URL: str = "https://datos.madrid.es" MADRID_OPENDATA_TIMEOUT: int = int(os.getenv("MADRID_OPENDATA_TIMEOUT", "30")) # Data Collection Configuration WEATHER_COLLECTION_INTERVAL_HOURS: int = int(os.getenv("WEATHER_COLLECTION_INTERVAL_HOURS", "1")) TRAFFIC_COLLECTION_INTERVAL_HOURS: int = int(os.getenv("TRAFFIC_COLLECTION_INTERVAL_HOURS", "1")) EVENTS_COLLECTION_INTERVAL_HOURS: int = int(os.getenv("EVENTS_COLLECTION_INTERVAL_HOURS", "6")) # Cache TTL Configuration WEATHER_CACHE_TTL_HOURS: int = int(os.getenv("WEATHER_CACHE_TTL_HOURS", "1")) TRAFFIC_CACHE_TTL_HOURS: int = int(os.getenv("TRAFFIC_CACHE_TTL_HOURS", "1")) EVENTS_CACHE_TTL_HOURS: int = int(os.getenv("EVENTS_CACHE_TTL_HOURS", "6")) # Data Quality Configuration DATA_VALIDATION_ENABLED: bool = os.getenv("DATA_VALIDATION_ENABLED", "true").lower() == "true" OUTLIER_DETECTION_ENABLED: bool = os.getenv("OUTLIER_DETECTION_ENABLED", "true").lower() == "true" DATA_COMPLETENESS_THRESHOLD: float = float(os.getenv("DATA_COMPLETENESS_THRESHOLD", "0.8")) # Geolocation Settings (Madrid focus) DEFAULT_LATITUDE: float = float(os.getenv("DEFAULT_LATITUDE", "40.4168")) # Madrid DEFAULT_LONGITUDE: float = float(os.getenv("DEFAULT_LONGITUDE", "-3.7038")) # Madrid LOCATION_RADIUS_KM: float = float(os.getenv("LOCATION_RADIUS_KM", "50.0")) # Data Retention RAW_DATA_RETENTION_DAYS: int = int(os.getenv("RAW_DATA_RETENTION_DAYS", "90")) PROCESSED_DATA_RETENTION_DAYS: int = int(os.getenv("PROCESSED_DATA_RETENTION_DAYS", "365")) # Batch Processing BATCH_PROCESSING_ENABLED: bool = os.getenv("BATCH_PROCESSING_ENABLED", "true").lower() == "true" BATCH_SIZE: int = int(os.getenv("BATCH_SIZE", "1000")) PARALLEL_PROCESSING_WORKERS: int = int(os.getenv("PARALLEL_PROCESSING_WORKERS", "4")) settings = DataSettings()