99from src .oncall_agent .api .schemas import (
1010 ActionType ,
1111 AIAnalysis ,
12- IncidentAction ,
1312 Incident ,
13+ IncidentAction ,
1414 IncidentStatus ,
1515 Severity ,
1616)
@@ -44,7 +44,7 @@ async def get_pool() -> asyncpg.Pool:
4444 if not postgres_url :
4545 raise RuntimeError ("No PostgreSQL connection URL configured (POSTGRES_URL, DATABASE_URL, or NEON_DATABASE_URL)" )
4646
47- logger .info (f "Connecting to PostgreSQL database..." )
47+ logger .info ("Connecting to PostgreSQL database..." )
4848 _pool = await asyncpg .create_pool (
4949 postgres_url ,
5050 min_size = 2 ,
@@ -105,6 +105,16 @@ async def _init_tables() -> None:
105105 )
106106 """ )
107107
108+ # Create incident_reports table
109+ await conn .execute ("""
110+ CREATE TABLE IF NOT EXISTS incident_reports (
111+ incident_id TEXT PRIMARY KEY REFERENCES incidents(id) ON DELETE CASCADE,
112+ json_report JSONB NOT NULL,
113+ markdown_report TEXT NOT NULL,
114+ generated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
115+ )
116+ """ )
117+
108118 # Create indexes for common queries
109119 await conn .execute ("""
110120 CREATE INDEX IF NOT EXISTS idx_incidents_status ON incidents(status)
@@ -444,16 +454,6 @@ async def generate_and_save(incident_id: str) -> dict[str, Any]:
444454 now = datetime .now (UTC )
445455
446456 async with pool .acquire () as conn :
447- # Create reports table if not exists
448- await conn .execute ("""
449- CREATE TABLE IF NOT EXISTS incident_reports (
450- incident_id TEXT PRIMARY KEY REFERENCES incidents(id) ON DELETE CASCADE,
451- json_report JSONB NOT NULL,
452- markdown_report TEXT NOT NULL,
453- generated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
454- )
455- """ )
456-
457457 await conn .execute (
458458 """
459459 INSERT INTO incident_reports (incident_id, json_report, markdown_report, generated_at)
@@ -563,13 +563,13 @@ def _generate_markdown_report(incident: Incident, analysis: dict) -> str:
563563 md_lines .append (ai_data ['analysis' ])
564564 else :
565565 if ai_data .get ('summary' ):
566- md_lines .extend ([f "### Summary" , "" , ai_data ['summary' ], "" ])
566+ md_lines .extend (["### Summary" , "" , ai_data ['summary' ], "" ])
567567 if ai_data .get ('root_cause' ):
568- md_lines .extend ([f "### Root Cause" , "" , ai_data ['root_cause' ], "" ])
568+ md_lines .extend (["### Root Cause" , "" , ai_data ['root_cause' ], "" ])
569569 if ai_data .get ('impact_assessment' ):
570- md_lines .extend ([f "### Impact Assessment" , "" , ai_data ['impact_assessment' ], "" ])
570+ md_lines .extend (["### Impact Assessment" , "" , ai_data ['impact_assessment' ], "" ])
571571 if ai_data .get ('recommended_actions' ):
572- md_lines .extend ([f "### Recommended Actions" , "" ])
572+ md_lines .extend (["### Recommended Actions" , "" ])
573573 for i , action in enumerate (ai_data ['recommended_actions' ], 1 ):
574574 if isinstance (action , dict ):
575575 md_lines .append (f"{ i } . **{ action .get ('action' , 'Unknown' )} **: { action .get ('reason' , '' )} " )
@@ -617,23 +617,31 @@ def _generate_markdown_report(incident: Incident, analysis: dict) -> str:
617617 @staticmethod
618618 async def get_saved_report (incident_id : str ) -> dict [str , Any ] | None :
619619 """Get saved reports for an incident."""
620- pool = await get_pool ()
620+ try :
621+ pool = await get_pool ()
621622
622- async with pool .acquire () as conn :
623- row = await conn .fetchrow (
624- "SELECT json_report, markdown_report, generated_at FROM incident_reports WHERE incident_id = $1" ,
625- incident_id
626- )
623+ async with pool .acquire () as conn :
624+ row = await conn .fetchrow (
625+ "SELECT json_report, markdown_report, generated_at FROM incident_reports WHERE incident_id = $1" ,
626+ incident_id
627+ )
627628
628- if not row :
629+ if not row :
630+ return None
631+
632+ json_data = row ['json_report' ]
633+ return {
634+ "json_report" : json_data if isinstance (json_data , dict ) else json .loads (json_data ),
635+ "markdown_report" : row ['markdown_report' ],
636+ "generated_at" : row ['generated_at' ].isoformat () if row ['generated_at' ] else None ,
637+ }
638+ except asyncpg .exceptions .UndefinedTableError :
639+ # Table doesn't exist yet - return None and let caller generate on-the-fly
640+ logger .warning (f"incident_reports table does not exist, returning None for incident { incident_id } " )
641+ return None
642+ except Exception as e :
643+ logger .error (f"Error getting saved report for { incident_id } : { e } " )
629644 return None
630-
631- json_data = row ['json_report' ]
632- return {
633- "json_report" : json_data if isinstance (json_data , dict ) else json .loads (json_data ),
634- "markdown_report" : row ['markdown_report' ],
635- "generated_at" : row ['generated_at' ].isoformat () if row ['generated_at' ] else None ,
636- }
637645
638646
639647async def check_database_health () -> dict [str , Any ]:
@@ -642,7 +650,7 @@ async def check_database_health() -> dict[str, Any]:
642650 pool = await get_pool ()
643651 async with pool .acquire () as conn :
644652 # Test query
645- result = await conn .fetchval ("SELECT 1" )
653+ await conn .fetchval ("SELECT 1" )
646654
647655 # Get some stats
648656 incident_count = await conn .fetchval ("SELECT COUNT(*) FROM incidents" )
0 commit comments