forked from AntonioMrtz/SpotifyElectron
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhealth_controller.py
121 lines (100 loc) · 4.17 KB
/
health_controller.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""
Health controller for handling incoming HTTP Requests
"""
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from starlette.status import HTTP_200_OK, HTTP_503_SERVICE_UNAVAILABLE
from app.auth.auth_schema import AuthConfig
from app.database.database_schema import DatabasePingFailedException
from app.database.DatabaseConnectionManager import DatabaseConnectionManager
from app.logging.logging_constants import LOGGING_HEALTH
from app.logging.logging_schema import SpotifyElectronLogger
from app.spotify_electron.health.health_schema import HealthCheckResponse
from app.spotify_electron.song.providers.song_service_provider import SongServiceProvider
router = APIRouter(prefix="/health", tags=["health"])
logger = SpotifyElectronLogger(LOGGING_HEALTH).getLogger()
def check_database_connection() -> dict[str, str]:
"""Validates ping to database
Returns:
dict[str, str]: Dictionary with status and explanatory message
"""
try:
if DatabaseConnectionManager.ping_database():
return {"status": "healthy", "message": "Database connection is active"}
except DatabasePingFailedException:
logger.exception(DatabasePingFailedException.ERROR)
else:
return {"status": "unhealthy", "message": DatabasePingFailedException.ERROR}
def check_song_service() -> dict[str, str]:
"""Validates if SongServiceProvider is inited
Returns:
dict[str, str]: Dictionary with status and explanatory message
"""
try:
service = SongServiceProvider.get_song_service()
except Exception as exception:
logger.exception("SongServiceProvider health check failed")
return {
"status": "unhealthy",
"message": f"SongServiceProvider check failed: {str(exception)}",
}
else:
if service is None:
return {"status": "unhealthy", "message": "SongServiceProvider is not initialized"}
return {"status": "healthy", "message": "SongServiceProvider is properly initialized"}
def check_auth_config() -> dict[str, str]:
"""Validates if auth configurations are set
Returns:
dict[str, str]: Dictionary with status and explanatory message
"""
try:
if not all(
[
hasattr(AuthConfig, "VERTIFICATION_ALGORITHM")
and AuthConfig.VERTIFICATION_ALGORITHM,
hasattr(AuthConfig, "ACCESS_TOKEN_EXPIRE_MINUTES")
and AuthConfig.ACCESS_TOKEN_EXPIRE_MINUTES,
hasattr(AuthConfig, "DAYS_TO_EXPIRE_COOKIE")
and AuthConfig.DAYS_TO_EXPIRE_COOKIE,
]
):
return {
"status": "unhealthy",
"message": "Auth configuration is not fully initialized",
}
except Exception:
logger.exception("Auth configuration health check failed")
return {
"status": "unhealthy",
"message": "Auth configuration check failed",
}
else:
return {"status": "healthy", "message": "Auth configuration is properly initialized"}
@router.get(
"/",
response_model=HealthCheckResponse,
summary="Health Check Endpoint",
description="Validates if the app and its critical components are functioning correctly",
)
async def get_health() -> JSONResponse:
"""Validates if the app has launched correctly and all critical components are healthy
Returns:
JSONResponse: health status with details of each component and status code
"""
db_health = check_database_connection()
service_health = check_song_service()
auth_health = check_auth_config()
health_details = {
"database": db_health,
"song_service": service_health,
"auth_config": auth_health,
}
is_healthy = all(check["status"] == "healthy" for check in health_details.values())
response_data = {
"status": "healthy" if is_healthy else "unhealthy",
"details": health_details,
}
status_code = HTTP_200_OK if is_healthy else HTTP_503_SERVICE_UNAVAILABLE
if not is_healthy:
logger.warning(f"Health check failed: {health_details}")
return JSONResponse(content=response_data, status_code=status_code)