add configurable cloud api url and subpath routing support for reverse proxies
This commit is contained in:
+25
-19
@@ -19,10 +19,14 @@ def get_http_client() -> httpx.AsyncClient:
|
||||
)
|
||||
return _http_client
|
||||
|
||||
def get_cloud_base_url() -> str:
|
||||
url = getattr(settings, "cloud_api_url", None) or os.getenv("CLOUD_API_URL") or "https://services-api.a2zhealth.in/v1/contec-monitor"
|
||||
return url.rstrip("/")
|
||||
|
||||
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 concurrently.
|
||||
and to the Cloud server concurrently.
|
||||
Returns True if at least one forward succeeds.
|
||||
"""
|
||||
headers = {"Content-Type": "application/json"}
|
||||
@@ -59,16 +63,17 @@ async def forward_vitals_to_api(vitals: NormalizedVitals) -> bool:
|
||||
logger.warning(f"Error forwarding to primary API: {type(e).__name__} ({err_msg})")
|
||||
return False
|
||||
|
||||
# 2. Forward to Render Cloud Server
|
||||
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:
|
||||
# 2. Forward to Cloud Server
|
||||
async def _forward_cloud() -> bool:
|
||||
cloud_base = get_cloud_base_url()
|
||||
cloud_url = f"{cloud_base}/api/push-vitals"
|
||||
is_on_cloud = os.getenv("RENDER") is not None or os.getenv("PORT") == "10000" or "render.local" in os.getenv("HOSTNAME", "")
|
||||
if is_on_cloud and ("onrender.com" in cloud_base):
|
||||
return True
|
||||
try:
|
||||
url_with_key = render_url
|
||||
url_with_key = cloud_url
|
||||
if settings.api_token:
|
||||
url_with_key = f"{render_url}?api_key={settings.api_token}"
|
||||
url_with_key = f"{cloud_url}?api_key={settings.api_token}"
|
||||
|
||||
response = await client.post(
|
||||
url_with_key,
|
||||
@@ -76,28 +81,29 @@ async def forward_vitals_to_api(vitals: NormalizedVitals) -> bool:
|
||||
headers=headers
|
||||
)
|
||||
response.raise_for_status()
|
||||
logger.info(f"Successfully forwarded vitals to Render Cloud for device {vitals.device_id}")
|
||||
logger.info(f"Successfully forwarded vitals to Cloud API for device {vitals.device_id}")
|
||||
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})")
|
||||
logger.warning(f"Error forwarding to Cloud API: {type(e).__name__} ({err_msg})")
|
||||
return False
|
||||
|
||||
results = await asyncio.gather(_forward_primary(), _forward_render(), return_exceptions=True)
|
||||
results = await asyncio.gather(_forward_primary(), _forward_cloud(), 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:
|
||||
"""
|
||||
Synchronizes patient demographics assignment to Render Cloud Server.
|
||||
Synchronizes patient demographics assignment to Cloud Server.
|
||||
Ensures local and remote dashboards always show the exact same patient.
|
||||
"""
|
||||
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:
|
||||
cloud_base = get_cloud_base_url()
|
||||
is_on_cloud = os.getenv("RENDER") is not None or os.getenv("PORT") == "10000" or "render.local" in os.getenv("HOSTNAME", "")
|
||||
if is_on_cloud and ("onrender.com" in cloud_base):
|
||||
return True
|
||||
|
||||
client = get_http_client()
|
||||
render_assign_url = "https://contectfiveparamonitor.onrender.com/api/patient/assign"
|
||||
cloud_assign_url = f"{cloud_base}/api/patient/assign"
|
||||
payload = {
|
||||
"device_id": device_id,
|
||||
"mrn": patient_data.get("mrn") or patient_data.get("patient_id") or "",
|
||||
@@ -108,13 +114,13 @@ async def sync_patient_assignment_to_cloud(patient_data: dict, device_id: str) -
|
||||
"patient_type": patient_data.get("patient_type")
|
||||
}
|
||||
try:
|
||||
url_with_key = render_assign_url
|
||||
url_with_key = cloud_assign_url
|
||||
if settings.api_token:
|
||||
url_with_key = f"{render_assign_url}?api_key={settings.api_token}"
|
||||
url_with_key = f"{cloud_assign_url}?api_key={settings.api_token}"
|
||||
resp = await client.post(url_with_key, json=payload, headers={"Content-Type": "application/json"})
|
||||
resp.raise_for_status()
|
||||
logger.info(f"Successfully synced patient {payload['mrn']} ({payload['name']}) to Render Cloud for {device_id}")
|
||||
logger.info(f"Successfully synced patient {payload['mrn']} ({payload['name']}) to Cloud for {device_id}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not sync patient assignment to Render Cloud: {type(e).__name__} ({e})")
|
||||
logger.warning(f"Could not sync patient assignment to Cloud: {type(e).__name__} ({e})")
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user