jira-webhook-llm/api/handlers.py

139 lines
5.3 KiB
Python

from fastapi import APIRouter, Request, HTTPException, Depends
from fastapi.responses import JSONResponse
from typing import Dict, Any
import config
from llm.models import LLMResponse, JiraWebhookPayload, JiraAnalysisResponse
from database.database import get_db_session # Removed Session import here
from sqlalchemy.orm import Session # Added correct SQLAlchemy import
from database.crud import get_all_analysis_records, delete_all_analysis_records, get_analysis_by_id, create_analysis_record, get_pending_analysis_records, update_record_status
router = APIRouter(
prefix="/api",
tags=["API"]
)
@router.get("/request")
async def get_analysis_records_endpoint(db: Session = Depends(get_db_session)):
"""Get analysis records"""
try:
records = get_all_analysis_records(db)
return JSONResponse(
status_code=200,
content={"data": records}
)
except Exception as e:
return JSONResponse(
status_code=500,
content={"error": str(e)}
)
@router.post("/request", status_code=201)
async def create_analysis_record_endpoint(
payload: JiraWebhookPayload,
db: Session = Depends(get_db_session)
):
"""Create a new Jira analysis record"""
try:
db_record = create_analysis_record(db, payload)
return JSONResponse(
status_code=201,
content={"message": "Record created successfully", "record_id": db_record.id}
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to create record: {str(e)}")
@router.post("/test-llm")
async def test_llm_endpoint(db: Session = Depends(get_db_session)):
"""Test endpoint for LLM integration"""
try:
from llm.chains import llm
test_prompt = "What is 1 + 1? Respond only with the number."
response = llm.invoke(test_prompt)
return {
"status": "success",
"message": "LLM integration test successful",
"response": str(response)
}
except Exception as e:
return JSONResponse(
status_code=500,
content={
"status": "error",
"message": f"LLM test failed: {str(e)}"
}
)
@router.delete("/request")
async def delete_analysis_records_endpoint(db: Session = Depends(get_db_session)):
"""Delete analysis records"""
try:
deleted_count = delete_all_analysis_records(db)
return JSONResponse(
status_code=200,
content={"message": f"Successfully deleted {deleted_count} records", "deleted_count": deleted_count}
)
except Exception as e:
return JSONResponse(
status_code=500,
content={"error": str(e)})
@router.get("/request/{record_id}")
async def get_analysis_record_endpoint(record_id: int, db: Session = Depends(get_db_session)):
"""Get specific analysis record by ID"""
record = get_analysis_by_id(db, record_id)
if not record:
raise HTTPException(status_code=404, detail="Analysis record not found")
return JiraAnalysisResponse.model_validate(record)
@router.get("/queue/pending")
async def get_pending_queue_records_endpoint(db: Session = Depends(get_db_session)):
"""Get all pending or retrying analysis records."""
try:
records = get_pending_analysis_records(db)
# Convert records to serializable format
serialized_records = []
for record in records:
record_dict = JiraAnalysisResponse.model_validate(record).model_dump()
# Convert datetime fields to ISO format
record_dict["created_at"] = record_dict["created_at"].isoformat() if record_dict["created_at"] else None
record_dict["updated_at"] = record_dict["updated_at"].isoformat() if record_dict["updated_at"] else None
serialized_records.append(record_dict)
return JSONResponse(
status_code=200,
content={"data": serialized_records}
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")
@router.post("/queue/{record_id}/retry", status_code=200)
async def retry_analysis_record_endpoint(record_id: int, db: Session = Depends(get_db_session)):
"""Manually trigger a retry for a failed, processing or validation_failed analysis record."""
db_record = get_analysis_by_id(db, record_id)
if not db_record:
raise HTTPException(status_code=404, detail="Analysis record not found")
if db_record.status not in ["processing", "failed", "validation_failed"]:
raise HTTPException(status_code=400, detail=f"Record status is '{db_record.status}'. Only 'failed', 'processing' or 'validation_failed' records can be retried.")
# Reset status to pending and clear error message for retry
updated_record = update_record_status(
db=db,
record_id=record_id,
status="pending",
error_message=None,
analysis_result=None,
raw_response=None,
next_retry_at=None # Reset retry time
)
if not updated_record:
raise HTTPException(status_code=500, detail="Failed to update record for retry.")
return JSONResponse(
status_code=200,
content={"message": f"Record {record_id} marked for retry.", "record_id": updated_record.id}
)