| """ |
| 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 |
|
|
| 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 |
| """ |
| |
| 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)}) |
|
|
| |
| 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: |
| |
| allocation_settings = DEFAULTS.copy() |
|
|
| |
| 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 |
|
|