Spaces:
Runtime error
Runtime error
Increase timeout and add debugging for database connection
Browse files- Increase health check timeout from 1s to 10s for Neon cold starts
- Add connection timeout settings (30s) to asyncpg
- Add logging to verify DATABASE_URL is set
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- src/api/health.py +2 -2
- src/db/health.py +2 -2
- src/models/base.py +15 -0
src/api/health.py
CHANGED
|
@@ -22,8 +22,8 @@ from src.db.health import check_database_health, get_full_health_status
|
|
| 22 |
|
| 23 |
router = APIRouter(prefix="/health", tags=["Health"])
|
| 24 |
|
| 25 |
-
# Default timeout for health checks (
|
| 26 |
-
HEALTH_CHECK_TIMEOUT =
|
| 27 |
|
| 28 |
|
| 29 |
@router.get(
|
|
|
|
| 22 |
|
| 23 |
router = APIRouter(prefix="/health", tags=["Health"])
|
| 24 |
|
| 25 |
+
# Default timeout for health checks (10 seconds for Neon cold starts)
|
| 26 |
+
HEALTH_CHECK_TIMEOUT = 10.0
|
| 27 |
|
| 28 |
|
| 29 |
@router.get(
|
src/db/health.py
CHANGED
|
@@ -21,8 +21,8 @@ from src.models.base import get_engine
|
|
| 21 |
|
| 22 |
logger = logging.getLogger(__name__)
|
| 23 |
|
| 24 |
-
# Default timeout for health check queries (
|
| 25 |
-
DEFAULT_HEALTH_CHECK_TIMEOUT =
|
| 26 |
|
| 27 |
|
| 28 |
@dataclass
|
|
|
|
| 21 |
|
| 22 |
logger = logging.getLogger(__name__)
|
| 23 |
|
| 24 |
+
# Default timeout for health check queries (10 seconds for cold starts)
|
| 25 |
+
DEFAULT_HEALTH_CHECK_TIMEOUT = 10.0
|
| 26 |
|
| 27 |
|
| 28 |
@dataclass
|
src/models/base.py
CHANGED
|
@@ -8,6 +8,7 @@ This module provides async engine configuration with:
|
|
| 8 |
"""
|
| 9 |
|
| 10 |
import os
|
|
|
|
| 11 |
from functools import lru_cache
|
| 12 |
from typing import Optional
|
| 13 |
|
|
@@ -18,6 +19,8 @@ from sqlmodel import SQLModel
|
|
| 18 |
# Load environment variables
|
| 19 |
load_dotenv()
|
| 20 |
|
|
|
|
|
|
|
| 21 |
# Engine instance (singleton)
|
| 22 |
_engine: Optional[AsyncEngine] = None
|
| 23 |
|
|
@@ -34,6 +37,14 @@ def get_database_url() -> str:
|
|
| 34 |
"""
|
| 35 |
database_url = os.getenv("DATABASE_URL")
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
if not database_url:
|
| 38 |
raise ValueError(
|
| 39 |
"DATABASE_URL environment variable is not set. "
|
|
@@ -93,6 +104,10 @@ def get_engine() -> AsyncEngine:
|
|
| 93 |
pool_size=5,
|
| 94 |
max_overflow=10,
|
| 95 |
pool_pre_ping=True, # Verify connections before use
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
)
|
| 97 |
|
| 98 |
return _engine
|
|
|
|
| 8 |
"""
|
| 9 |
|
| 10 |
import os
|
| 11 |
+
import logging
|
| 12 |
from functools import lru_cache
|
| 13 |
from typing import Optional
|
| 14 |
|
|
|
|
| 19 |
# Load environment variables
|
| 20 |
load_dotenv()
|
| 21 |
|
| 22 |
+
logger = logging.getLogger(__name__)
|
| 23 |
+
|
| 24 |
# Engine instance (singleton)
|
| 25 |
_engine: Optional[AsyncEngine] = None
|
| 26 |
|
|
|
|
| 37 |
"""
|
| 38 |
database_url = os.getenv("DATABASE_URL")
|
| 39 |
|
| 40 |
+
# Log whether DATABASE_URL is set (without exposing the actual value)
|
| 41 |
+
if database_url:
|
| 42 |
+
# Mask the password in the URL for logging
|
| 43 |
+
masked_url = database_url.split("@")[1] if "@" in database_url else "set"
|
| 44 |
+
logger.info(f"DATABASE_URL is set, connecting to: ...@{masked_url}")
|
| 45 |
+
else:
|
| 46 |
+
logger.error("DATABASE_URL environment variable is NOT set!")
|
| 47 |
+
|
| 48 |
if not database_url:
|
| 49 |
raise ValueError(
|
| 50 |
"DATABASE_URL environment variable is not set. "
|
|
|
|
| 104 |
pool_size=5,
|
| 105 |
max_overflow=10,
|
| 106 |
pool_pre_ping=True, # Verify connections before use
|
| 107 |
+
connect_args={
|
| 108 |
+
"timeout": 30, # Connection timeout in seconds
|
| 109 |
+
"command_timeout": 30, # Query timeout in seconds
|
| 110 |
+
},
|
| 111 |
)
|
| 112 |
|
| 113 |
return _engine
|