Files
routesapi/app/services/rider/get_active_riders.py
Suriya 9ef2f61870 sync: capture the production server's code, which was never committed
/root/Routes-api on 31.97.228.132 is not a git repository. Work had been
done directly on the box and existed nowhere else -- a single rm -rf from
being lost, and impossible to review or roll back.

Deploying the previous HEAD over it would have silently reverted all of
this. Most visibly the Valhalla road-backend probe in main.py, whose own
comment explains why it exists: road sequencing degrades to aerial
silently by design, so an unreachable backend stays invisible, "which is
exactly how the expired Google key went unnoticed". Overwriting it would
have reintroduced precisely the failure it was written to catch, and the
service would have kept answering 200 throughout.

The server had also moved from Google Maps to Valhalla for road distance
(VALHALLA_URL, road_backend_status, +190 lines in route_optimizer),
extended docker-compose from 44 to 95 lines, and changed rider fetching,
health, dynamic config and the cache layer.

Only 10 files differ in substance. The other 27 that appeared to differ
were CRLF-vs-LF noise -- the server writes CRLF -- and are normalised to
LF here rather than committed as spurious whole-file rewrites.

Committed as-is, before any change of mine, so the diff that follows is
reviewable against what is actually running.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 15:56:32 +05:30

118 lines
4.3 KiB
Python

import httpx
import logging
from datetime import datetime
from typing import List, Dict, Any
logger = logging.getLogger(__name__)
def _roster_cache_ttl() -> int:
"""Roster cache TTL in seconds. 0 disables caching entirely."""
try:
from app.config.dynamic_config import get_config
return int(get_config().get("rider_roster_cache_ttl_seconds", 30))
except Exception:
return 30
async def fetch_active_riders() -> List[Dict[str, Any]]:
"""
Fetch active rider logs from the external API for the current date.
Returns a list of rider log dictionaries.
This upstream call measured ~6s on live traffic and was the single largest
component of riderassign latency, so successful responses are cached for
`rider_roster_cache_ttl_seconds`. The TTL is deliberately short: a rider
going on or off duty must become visible quickly, and the absent-rider
validation in the assignment path checks against this roster.
Only non-empty successes are cached. Caching an empty result or a failure
would turn a brief upstream blip into a full-TTL outage where every request
sees zero riders.
"""
today_str = datetime.now().strftime("%Y-%m-%d")
ttl = _roster_cache_ttl()
cache_key = f"riders:active:{today_str}"
if ttl > 0:
try:
from app.services import cache as _cache
cached = _cache.get_json(cache_key)
if isinstance(cached, list) and cached:
logger.debug(f"[Riders] roster cache hit ({len(cached)} riders)")
return cached
except Exception:
pass
try:
url = "https://jupiter.nearle.app/live/api/v2/partners/getriderlogs/"
params = {
"applocationid": 1,
"partnerid": 44,
"fromdate": today_str,
"todate": today_str,
"keyword": ""
}
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(url, params=params)
response.raise_for_status()
data = response.json()
if data and data.get("code") == 200 and data.get("details"):
# Filter riders who are in our preferences list and are 'active' or 'idle' (assuming we want online riders)
# The user's example showed "onduty": 1. We might want to filter by that.
# For now, returning all logs, filtering can happen in assignment logic or here.
# Let's return the raw list as requested, filtering logic will be applied during assignment.
riders = data.get("details", [])
if riders and ttl > 0:
try:
from app.services import cache as _cache
_cache.set_json(cache_key, riders, ttl_seconds=ttl)
except Exception:
pass
return riders
logger.warning(f"Fetch active riders returned no details: {data}")
return []
except Exception as e:
logger.error(f"Error fetching active riders: {e}", exc_info=True)
return []
async def fetch_created_orders() -> List[Dict[str, Any]]:
"""
Fetch all orders in 'created' state for the current date.
"""
try:
today_str = datetime.now().strftime("%Y-%m-%d")
url = "https://jupiter.nearle.app/live/api/v1/orders/tenant/getorders/"
# Removed pagesize as per user request to fetch all
params = {
"applocationid": 0,
"tenantid": 0,
"locationid": 0,
"status": "created",
"fromdate": today_str,
"todate": today_str,
"keyword": "",
"pageno": 1
# "pagesize" intentionally omitted to fetch all
}
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.get(url, params=params)
response.raise_for_status()
data = response.json()
if data and data.get("code") == 200 and data.get("details"):
return data.get("details", [])
logger.warning(f"Fetch created orders returned no details: {data}")
return []
except Exception as e:
logger.error(f"Error fetching created orders: {e}", exc_info=True)
return []