initial project setup with README and ignore

This commit is contained in:
2026-04-08 15:13:42 +05:30
commit 2d5688cb35
47 changed files with 7929 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
"""Controllers package."""
from .route_controller import RouteController
__all__ = ["RouteController"]

View File

@@ -0,0 +1,87 @@
"""Controller for provider payload optimization and forwarding."""
import logging
import hashlib
import json
from typing import Dict, Any
import httpx
from fastapi import HTTPException
from app.core.exceptions import ValidationError, APIException
from app.services.routing.route_optimizer import RouteOptimizer
from app.services import cache
logger = logging.getLogger(__name__)
class RouteController:
"""Controller for optimizing provider payloads and forwarding upstream."""
def __init__(self):
self.route_optimizer = RouteOptimizer()
def _hash_key(self, prefix: str, payload: Dict[str, Any]) -> str:
"""Create a stable cache key from a dict payload."""
# ensure deterministic json by sorting keys
serialized = json.dumps(payload, sort_keys=True, separators=(",", ":"))
digest = hashlib.sha256(serialized.encode("utf-8")).hexdigest()
return f"routes:{prefix}:{digest}"
async def optimize_and_forward_provider_payload(self, orders: list[dict], forward_url: str) -> dict:
"""Optimize provider payload and return it (forwarding paused).
- Input: list of provider orders (dicts)
- Output: {code, details, message, status} where details is the optimized array
"""
try:
if not isinstance(orders, list) or not orders:
raise ValidationError("Orders array is required", field="body")
optimized = await self.route_optimizer.optimize_provider_payload(orders)
# Debug sample of optimized payload (first 3 items, select keys)
try:
sample = [
{
k: item.get(k)
for k in ("orderheaderid", "orderid", "deliverycustomerid", "step", "previouskms", "cumulativekms", "eta")
}
for item in optimized[:3]
]
logger.debug(f"Optimized payload sample: {sample}")
trace = [
{
"orderid": item.get("orderid"),
"step": item.get("step"),
"prev": item.get("previouskms"),
"cum": item.get("cumulativekms"),
}
for item in optimized
]
logger.debug(f"Optimized order trace: {trace}")
except Exception:
logger.debug("Optimized payload sample logging failed")
# Forwarding paused: return optimized payload directly
return {
"code": 200,
"details": optimized,
"message": "Success",
"status": True,
}
except ValidationError:
raise
except httpx.HTTPStatusError as e:
status_code = e.response.status_code
body_text = e.response.text
logger.error(f"Forwarding failed: {status_code} - {body_text}")
# Surface upstream details to the client for faster debugging
raise APIException(
status_code=502,
message=f"Upstream service error (status {status_code}): {body_text}",
code="UPSTREAM_ERROR"
)
except Exception as e:
logger.error(f"Error optimizing/forwarding provider payload: {e}", exc_info=True)
raise APIException(status_code=500, message="Internal server error", code="INTERNAL_ERROR")
# Batch routes removed - use single-route optimization for each pickup location