fix: reliable cloud sync and connection pooling for Render live dashboard

This commit is contained in:
2026-09-17 16:41:52 +05:30
parent 68bda2519f
commit 37445d2ae9
8 changed files with 286 additions and 48 deletions
+25 -19
View File
@@ -1,5 +1,7 @@
import httpx
import logging
import asyncio
import os
from typing import Optional
from schemas import NormalizedVitals
from config import settings
@@ -12,18 +14,17 @@ def get_http_client() -> httpx.AsyncClient:
global _http_client
if _http_client is None or _http_client.is_closed:
_http_client = httpx.AsyncClient(
timeout=httpx.Timeout(connect=3.0, read=5.0, write=3.0, pool=3.0),
limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
timeout=httpx.Timeout(connect=5.0, read=5.0, write=5.0, pool=10.0),
limits=httpx.Limits(max_keepalive_connections=20, max_connections=50)
)
return _http_client
async def forward_vitals_to_api(vitals: NormalizedVitals) -> bool:
"""
Attempts to POST the normalized vitals to the configured target API
and to the Render cloud database.
and to the Render cloud database concurrently.
Returns True if at least one forward succeeds.
"""
import os
headers = {"Content-Type": "application/json"}
# Strip heavy wave sample arrays before REST transmission (cloud APIs only ingest vital signs)
@@ -31,12 +32,16 @@ async def forward_vitals_to_api(vitals: NormalizedVitals) -> bool:
payload.pop("ecg_wave", None)
payload.pop("pleth_wave", None)
if not payload.get("patient_id"):
payload["patient_id"] = "UNKNOWN"
client = get_http_client()
# 1. Forward to primary target API (e.g. Injomo Dev Workflow)
primary_url = settings.target_api_url
primary_success = False
if primary_url:
async def _forward_primary() -> bool:
primary_url = settings.target_api_url
if not primary_url:
return False
try:
primary_headers = headers.copy()
if settings.api_token:
@@ -48,19 +53,18 @@ async def forward_vitals_to_api(vitals: NormalizedVitals) -> bool:
)
response.raise_for_status()
logger.info(f"Successfully forwarded vitals to primary API for device {vitals.device_id}")
primary_success = True
return True
except Exception as e:
err_msg = str(e).strip() or "timeout / connection reset"
logger.warning(f"Error forwarding to primary API: {type(e).__name__} ({err_msg})")
return False
# 2. Forward to Render Cloud Server
render_url = "https://contectfiveparamonitor.onrender.com/api/push-vitals"
render_success = False
# Detect if we are already running on Render to prevent an infinite loop
is_on_render = os.getenv("RENDER") is not None or os.getenv("PORT") == "10000" or "render.local" in os.getenv("HOSTNAME", "")
if not is_on_render:
async def _forward_render() -> bool:
render_url = "https://contectfiveparamonitor.onrender.com/api/push-vitals"
is_on_render = os.getenv("RENDER") is not None or os.getenv("PORT") == "10000" or "render.local" in os.getenv("HOSTNAME", "")
if is_on_render:
return True
try:
url_with_key = render_url
if settings.api_token:
@@ -73,12 +77,14 @@ async def forward_vitals_to_api(vitals: NormalizedVitals) -> bool:
)
response.raise_for_status()
logger.info(f"Successfully forwarded vitals to Render Cloud for device {vitals.device_id}")
render_success = True
return True
except Exception as e:
err_msg = str(e).strip() or "timeout / connection reset"
logger.warning(f"Error forwarding to Render Cloud: {type(e).__name__} ({err_msg})")
return primary_success or render_success
return False
results = await asyncio.gather(_forward_primary(), _forward_render(), return_exceptions=True)
return any(r is True for r in results if not isinstance(r, Exception))
async def sync_patient_assignment_to_cloud(patient_data: dict, device_id: str) -> bool:
@@ -86,7 +92,6 @@ async def sync_patient_assignment_to_cloud(patient_data: dict, device_id: str) -
Synchronizes patient demographics assignment to Render Cloud Server.
Ensures local and remote dashboards always show the exact same patient.
"""
import os
is_on_render = os.getenv("RENDER") is not None or os.getenv("PORT") == "10000" or "render.local" in os.getenv("HOSTNAME", "")
if is_on_render:
return True
@@ -100,6 +105,7 @@ async def sync_patient_assignment_to_cloud(patient_data: dict, device_id: str) -
"dob": patient_data.get("dob") or patient_data.get("patient_dob"),
"gender": patient_data.get("gender") or patient_data.get("patient_gender"),
"bed_id": patient_data.get("bed_id"),
"patient_type": patient_data.get("patient_type")
}
try:
url_with_key = render_assign_url