fix: Fix ImportError in alert_processor alerts.py by using DatabaseManager pattern

The alert_processor service was crashing with:
ImportError: cannot import name 'get_db' from 'shared.database.base'

Root cause: alerts.py was using Depends(get_db) pattern which doesn't exist
in shared.database.base.

Fix: Refactored alerts.py to follow the same pattern as analytics.py:
- Removed Depends(get_db) dependency injection
- Each endpoint now creates a DatabaseManager instance
- Uses db_manager.get_session() context manager for database access

This matches the alert_processor service's existing architecture in analytics.py.
This commit is contained in:
Claude
2025-11-07 22:27:58 +00:00
parent bc97fc0d1a
commit c0d58824ba

View File

@@ -3,15 +3,13 @@
Alerts API endpoints for dashboard and alert management Alerts API endpoints for dashboard and alert management
""" """
from fastapi import APIRouter, Depends, HTTPException, Query, Path from fastapi import APIRouter, HTTPException, Query, Path
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List, Optional from typing import List, Optional
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from uuid import UUID from uuid import UUID
from datetime import datetime from datetime import datetime
import structlog import structlog
from shared.database.base import get_db
from app.repositories.alerts_repository import AlertsRepository from app.repositories.alerts_repository import AlertsRepository
from app.models.alerts import AlertSeverity, AlertStatus from app.models.alerts import AlertSeverity, AlertStatus
@@ -76,8 +74,7 @@ class AlertsListResponse(BaseModel):
description="Get summary of alerts by severity and status for dashboard health indicator" description="Get summary of alerts by severity and status for dashboard health indicator"
) )
async def get_alerts_summary( async def get_alerts_summary(
tenant_id: UUID = Path(..., description="Tenant ID"), tenant_id: UUID = Path(..., description="Tenant ID")
db: AsyncSession = Depends(get_db)
) -> AlertsSummaryResponse: ) -> AlertsSummaryResponse:
""" """
Get alerts summary for dashboard Get alerts summary for dashboard
@@ -85,10 +82,17 @@ async def get_alerts_summary(
Returns counts of alerts grouped by severity and status. Returns counts of alerts grouped by severity and status.
Critical count maps to URGENT severity for dashboard compatibility. Critical count maps to URGENT severity for dashboard compatibility.
""" """
from app.config import AlertProcessorConfig
from shared.database.base import create_database_manager
try: try:
repo = AlertsRepository(db) config = AlertProcessorConfig()
summary = await repo.get_alerts_summary(tenant_id) db_manager = create_database_manager(config.DATABASE_URL, "alert-processor")
return AlertsSummaryResponse(**summary)
async with db_manager.get_session() as session:
repo = AlertsRepository(session)
summary = await repo.get_alerts_summary(tenant_id)
return AlertsSummaryResponse(**summary)
except Exception as e: except Exception as e:
logger.error("Error getting alerts summary", error=str(e), tenant_id=str(tenant_id)) logger.error("Error getting alerts summary", error=str(e), tenant_id=str(tenant_id))
@@ -107,8 +111,7 @@ async def get_alerts(
status: Optional[str] = Query(None, description="Filter by status: active, resolved, acknowledged, ignored"), status: Optional[str] = Query(None, description="Filter by status: active, resolved, acknowledged, ignored"),
resolved: Optional[bool] = Query(None, description="Filter by resolved status: true=resolved only, false=unresolved only"), resolved: Optional[bool] = Query(None, description="Filter by resolved status: true=resolved only, false=unresolved only"),
limit: int = Query(100, ge=1, le=1000, description="Maximum number of results"), limit: int = Query(100, ge=1, le=1000, description="Maximum number of results"),
offset: int = Query(0, ge=0, description="Pagination offset"), offset: int = Query(0, ge=0, description="Pagination offset")
db: AsyncSession = Depends(get_db)
) -> AlertsListResponse: ) -> AlertsListResponse:
""" """
Get filtered list of alerts Get filtered list of alerts
@@ -119,6 +122,9 @@ async def get_alerts(
- resolved: boolean filter for resolved status - resolved: boolean filter for resolved status
- pagination: limit and offset - pagination: limit and offset
""" """
from app.config import AlertProcessorConfig
from shared.database.base import create_database_manager
try: try:
# Validate severity enum # Validate severity enum
if severity and severity not in [s.value for s in AlertSeverity]: if severity and severity not in [s.value for s in AlertSeverity]:
@@ -134,43 +140,47 @@ async def get_alerts(
detail=f"Invalid status. Must be one of: {[s.value for s in AlertStatus]}" detail=f"Invalid status. Must be one of: {[s.value for s in AlertStatus]}"
) )
repo = AlertsRepository(db) config = AlertProcessorConfig()
alerts = await repo.get_alerts( db_manager = create_database_manager(config.DATABASE_URL, "alert-processor")
tenant_id=tenant_id,
severity=severity,
status=status,
resolved=resolved,
limit=limit,
offset=offset
)
# Convert to response models async with db_manager.get_session() as session:
alert_responses = [ repo = AlertsRepository(session)
AlertResponse( alerts = await repo.get_alerts(
id=str(alert.id), tenant_id=tenant_id,
tenant_id=str(alert.tenant_id), severity=severity,
item_type=alert.item_type, status=status,
alert_type=alert.alert_type, resolved=resolved,
severity=alert.severity, limit=limit,
status=alert.status, offset=offset
service=alert.service,
title=alert.title,
message=alert.message,
actions=alert.actions,
alert_metadata=alert.alert_metadata,
created_at=alert.created_at,
updated_at=alert.updated_at,
resolved_at=alert.resolved_at
) )
for alert in alerts
]
return AlertsListResponse( # Convert to response models
alerts=alert_responses, alert_responses = [
total=len(alert_responses), # In a real implementation, you'd query the total count separately AlertResponse(
limit=limit, id=str(alert.id),
offset=offset tenant_id=str(alert.tenant_id),
) item_type=alert.item_type,
alert_type=alert.alert_type,
severity=alert.severity,
status=alert.status,
service=alert.service,
title=alert.title,
message=alert.message,
actions=alert.actions,
alert_metadata=alert.alert_metadata,
created_at=alert.created_at,
updated_at=alert.updated_at,
resolved_at=alert.resolved_at
)
for alert in alerts
]
return AlertsListResponse(
alerts=alert_responses,
total=len(alert_responses), # In a real implementation, you'd query the total count separately
limit=limit,
offset=offset
)
except HTTPException: except HTTPException:
raise raise
@@ -187,33 +197,39 @@ async def get_alerts(
) )
async def get_alert( async def get_alert(
tenant_id: UUID = Path(..., description="Tenant ID"), tenant_id: UUID = Path(..., description="Tenant ID"),
alert_id: UUID = Path(..., description="Alert ID"), alert_id: UUID = Path(..., description="Alert ID")
db: AsyncSession = Depends(get_db)
) -> AlertResponse: ) -> AlertResponse:
"""Get a specific alert by ID""" """Get a specific alert by ID"""
from app.config import AlertProcessorConfig
from shared.database.base import create_database_manager
try: try:
repo = AlertsRepository(db) config = AlertProcessorConfig()
alert = await repo.get_alert_by_id(tenant_id, alert_id) db_manager = create_database_manager(config.DATABASE_URL, "alert-processor")
if not alert: async with db_manager.get_session() as session:
raise HTTPException(status_code=404, detail="Alert not found") repo = AlertsRepository(session)
alert = await repo.get_alert_by_id(tenant_id, alert_id)
return AlertResponse( if not alert:
id=str(alert.id), raise HTTPException(status_code=404, detail="Alert not found")
tenant_id=str(alert.tenant_id),
item_type=alert.item_type, return AlertResponse(
alert_type=alert.alert_type, id=str(alert.id),
severity=alert.severity, tenant_id=str(alert.tenant_id),
status=alert.status, item_type=alert.item_type,
service=alert.service, alert_type=alert.alert_type,
title=alert.title, severity=alert.severity,
message=alert.message, status=alert.status,
actions=alert.actions, service=alert.service,
alert_metadata=alert.alert_metadata, title=alert.title,
created_at=alert.created_at, message=alert.message,
updated_at=alert.updated_at, actions=alert.actions,
resolved_at=alert.resolved_at alert_metadata=alert.alert_metadata,
) created_at=alert.created_at,
updated_at=alert.updated_at,
resolved_at=alert.resolved_at
)
except HTTPException: except HTTPException:
raise raise