cuatrolabs-booking-allocation-ms / app /core /settings_loader.py
Michael-Antony's picture
feat: implement booking allocation engine (Phases 1–10)
e6033f2
"""
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