Spaces:
Sleeping
Sleeping
| from typing import Any, Dict, List, Optional | |
| from fastapi import APIRouter, Header, HTTPException | |
| import requests | |
| from app.core.config import ( | |
| SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, | |
| SUPABASE_TIMEOUT_SECONDS, SUPABASE_RAW_BUCKET, SUPABASE_PROCESSED_BUCKET, | |
| SUPABASE_ENFORCE_AUTH, MODEL_INFERENCE_PROVIDER, MODEL_SERVICE_ENABLE_LOCAL_ENDPOINT, | |
| MODEL_PATHS, MODELS_DIR, PARKING_HOURLY_RATE_EGP, PARKING_DAILY_RATE_EGP, | |
| PARKING_EXTRA_AFTER_FIRST_HOUR_EGP, PARKING_BILLING_MODE, PARKING_LOCATION_HOURLY_RATES, | |
| PARKING_LOCATION_PRICING, PARKING_LOCATION_CAPACITIES, GARAGE_TOTAL_CAPACITY, | |
| APP_SERVICE_FEE_EGP, CORE_TABLES, | |
| supabase_configured, model_service_configured, resolve_model_service_infer_url, | |
| should_load_local_models, LOGGER, | |
| ) | |
| from app.services.supabase_client import supabase_list_buckets, supabase_table_exists | |
| from app.security.auth import require_authenticated_user, require_developer_user, _supabase_headers | |
| router = APIRouter(tags=["health"]) | |
| def health(): | |
| local_models_required = should_load_local_models() | |
| status_value = "ok" | |
| model_inference_payload: Dict[str, Any] = { | |
| "provider": MODEL_INFERENCE_PROVIDER, | |
| "local_models_required": local_models_required, | |
| "local_endpoint_enabled": MODEL_SERVICE_ENABLE_LOCAL_ENDPOINT, | |
| "remote_service_configured": model_service_configured(), | |
| "remote_infer_url": resolve_model_service_infer_url(), | |
| } | |
| return { | |
| "status": status_value, | |
| "model_inference": model_inference_payload, | |
| "supabase_configured": supabase_configured(), | |
| "supabase_auth_enforced": SUPABASE_ENFORCE_AUTH, | |
| "pricing": { | |
| "default_billing_mode": PARKING_BILLING_MODE, | |
| "default_hourly_rate_egp": round(max(0.0, PARKING_HOURLY_RATE_EGP), 2), | |
| "default_daily_rate_egp": round(max(0.0, PARKING_DAILY_RATE_EGP), 2), | |
| "default_extra_after_first_hour_egp": round(max(0.0, PARKING_EXTRA_AFTER_FIRST_HOUR_EGP), 2), | |
| "location_hourly_rates": PARKING_LOCATION_HOURLY_RATES, | |
| "location_pricing": PARKING_LOCATION_PRICING, | |
| "location_capacities": PARKING_LOCATION_CAPACITIES, | |
| "garage_total_capacity": GARAGE_TOTAL_CAPACITY, | |
| "app_service_fee_egp": round(max(0.0, APP_SERVICE_FEE_EGP), 2), | |
| }, | |
| } | |
| def supabase_health(): | |
| if not supabase_configured(): | |
| return {"status": "disabled", "reason": "Set SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY"} | |
| try: | |
| response = requests.get( | |
| f"{SUPABASE_URL}/auth/v1/settings", | |
| headers={"apikey": SUPABASE_ANON_KEY}, | |
| timeout=SUPABASE_TIMEOUT_SECONDS, | |
| ) | |
| if response.status_code != 200: | |
| return {"status": "error", "http_status": response.status_code, "detail": response.text[:400]} | |
| existing_buckets = set(supabase_list_buckets()) | |
| required_buckets = {SUPABASE_RAW_BUCKET, SUPABASE_PROCESSED_BUCKET} | |
| missing_buckets = sorted(required_buckets - existing_buckets) | |
| table_checks: Dict[str, Any] = {} | |
| all_tables_ready = True | |
| for table_name in sorted(CORE_TABLES): | |
| exists, detail = supabase_table_exists(table_name) | |
| table_checks[table_name] = {"exists": exists, "detail": detail} | |
| if not exists: | |
| all_tables_ready = False | |
| ready_for_persistence = all_tables_ready and not missing_buckets | |
| return { | |
| "status": "ok" if ready_for_persistence else "partial", | |
| "url": SUPABASE_URL, | |
| "readiness": { | |
| "ready_for_persistence": ready_for_persistence, | |
| "missing_buckets": missing_buckets, | |
| "tables": table_checks, | |
| }, | |
| } | |
| except requests.RequestException as exc: | |
| return {"status": "error", "detail": str(exc)} | |
| def models(): | |
| return { | |
| "inference_provider": MODEL_INFERENCE_PROVIDER, | |
| "local_models_required": should_load_local_models(), | |
| "remote_service_configured": model_service_configured(), | |
| "remote_infer_url": resolve_model_service_infer_url(), | |
| } | |
| def developer_models(authorization: Optional[str] = Header(default=None)): | |
| request_user, requester_role = require_developer_user(authorization) | |
| return models() | |