Coverage for src/alprina_cli/api/routes/health_check.py: 0%

37 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-11-14 11:27 +0100

1""" 

2Health check and diagnostics endpoints. 

3""" 

4 

5from fastapi import APIRouter 

6from typing import Dict, Any 

7from loguru import logger 

8 

9from ..services.neon_service import neon_service 

10 

11router = APIRouter() 

12 

13 

14@app.get("/v1/health/detailed") 

15async def detailed_health_check() -> Dict[str, Any]: 

16 """ 

17 Detailed health check with database connection status. 

18 """ 

19 health = { 

20 "api": "healthy", 

21 "database": { 

22 "enabled": False, 

23 "connected": False, 

24 "pool_initialized": False, 

25 "error": None 

26 } 

27 } 

28 

29 # Check Neon service 

30 if neon_service.is_enabled(): 

31 health["database"]["enabled"] = True 

32 

33 try: 

34 pool = await neon_service.get_pool() 

35 health["database"]["pool_initialized"] = True 

36 

37 # Test query 

38 async with pool.acquire() as conn: 

39 version = await conn.fetchval("SELECT version()") 

40 health["database"]["connected"] = True 

41 health["database"]["version"] = version[:50] # First 50 chars 

42 

43 # Count tables 

44 table_count = await conn.fetchval( 

45 """ 

46 SELECT COUNT(*) FROM information_schema.tables 

47 WHERE table_schema = 'public' 

48 """ 

49 ) 

50 health["database"]["tables_count"] = table_count 

51 

52 # Count rows in key tables 

53 health["database"]["row_counts"] = { 

54 "users": await conn.fetchval("SELECT COUNT(*) FROM users"), 

55 "webhook_events": await conn.fetchval("SELECT COUNT(*) FROM webhook_events"), 

56 "api_keys": await conn.fetchval("SELECT COUNT(*) FROM api_keys"), 

57 "scans": await conn.fetchval("SELECT COUNT(*) FROM scans") 

58 } 

59 

60 except Exception as e: 

61 health["database"]["error"] = str(e) 

62 logger.error(f"Health check database error: {e}") 

63 

64 return health 

65 

66 

67@app.get("/v1/health/database-test") 

68async def database_test() -> Dict[str, Any]: 

69 """ 

70 Test database write capability. 

71 """ 

72 if not neon_service.is_enabled(): 

73 return {"error": "Database not enabled"} 

74 

75 try: 

76 pool = await neon_service.get_pool() 

77 

78 async with pool.acquire() as conn: 

79 # Try to insert a test webhook event 

80 await conn.execute( 

81 """ 

82 INSERT INTO webhook_events (event_type, event_id, payload) 

83 VALUES ($1, $2, $3) 

84 ON CONFLICT (event_id) DO NOTHING 

85 """, 

86 "test.health_check", 

87 f"test_health_{datetime.utcnow().timestamp()}", 

88 {"test": True} 

89 ) 

90 

91 # Count webhooks 

92 count = await conn.fetchval("SELECT COUNT(*) FROM webhook_events") 

93 

94 return { 

95 "status": "success", 

96 "message": "Database write test passed", 

97 "webhook_events_count": count 

98 } 

99 

100 except Exception as e: 

101 logger.error(f"Database test failed: {e}") 

102 return { 

103 "status": "error", 

104 "message": str(e) 

105 }