""" Settings loader with 3-layer fallback: Redis cache → MongoDB → .env defaults. Loads booking allocation settings from scm_merchant_settings (merchant_type='company'). """ import json import logging import redis.asyncio as redis from app.core.config import settings logger = logging.getLogger(__name__) SETTINGS_CACHE_KEY = "merchant_settings:company" SETTINGS_CACHE_TTL = 86400 # 24 hours DEFAULTS = { "allocation_lead_time_minutes": settings.ALLOCATION_LEAD_TIME_MINUTES, "scheduler_window_buffer_minutes": settings.SCHEDULER_WINDOW_BUFFER_MINUTES, "scheduler_poll_interval_seconds": settings.SCHEDULER_POLL_INTERVAL_SECONDS, "offer_expiry_seconds": settings.OFFER_EXPIRY_SECONDS, "reschedule_cutoff_minutes": 180, "queue_alert_threshold": settings.QUEUE_ALERT_THRESHOLD, "max_offer_retries": settings.MAX_OFFER_RETRIES, "max_partner_distance_km": 50, "scoring_weights": { "distance": 0.40, "rating": 0.30, "load": 0.20, "experience": 0.10, }, } async def get_allocation_settings(redis_client: redis.Redis, mongo_db=None) -> dict: """ Load allocation settings with 3-layer fallback. Layer 1: Redis cache (24hr TTL) Layer 2: MongoDB scm_merchant_settings Layer 3: .env defaults — never crash """ # Layer 1: Redis cache try: cached = await redis_client.get(SETTINGS_CACHE_KEY) if cached: return json.loads(cached) except Exception as e: logger.warning("Redis cache read failed", extra={"error": str(e)}) # Layer 2: MongoDB allocation_settings = None if mongo_db is not None: try: doc = await mongo_db["scm_merchant_settings"].find_one( {"merchant_type": "company", "is_active": True}, {"booking_allocation": 1, "_id": 0}, ) if doc and "booking_allocation" in doc: allocation_settings = {**DEFAULTS, **doc["booking_allocation"]} except Exception as e: logger.warning("MongoDB settings fetch failed — using defaults", extra={"error": str(e)}) if allocation_settings is None: # Layer 3: .env defaults allocation_settings = DEFAULTS.copy() # Cache in Redis for next call try: await redis_client.set( SETTINGS_CACHE_KEY, json.dumps(allocation_settings), ex=SETTINGS_CACHE_TTL, ) except Exception as e: logger.warning("Redis cache write failed", extra={"error": str(e)}) return allocation_settings