from loguru import logger from sqlalchemy.orm import Session from datetime import datetime, timezone import json from typing import Dict, Any, Optional from database.models import JiraAnalysis from llm.models import JiraWebhookPayload def create_analysis_record(db: Session, payload: JiraWebhookPayload) -> JiraAnalysis: """Creates a new Jira analysis record in the database.""" db_analysis = JiraAnalysis( issue_key=payload.issueKey, status="pending", issue_summary=payload.summary, request_payload=payload.model_dump(), created_at=datetime.now(timezone.utc), updated_at=datetime.now(timezone.utc), retry_count=0, last_processed_at=None, next_retry_at=None ) db.add(db_analysis) db.commit() db.refresh(db_analysis) return db_analysis def get_analysis_record(db: Session, issue_key: str) -> Optional[JiraAnalysis]: """Retrieves the latest analysis record for a given Jira issue key.""" logger.debug(f"Attempting to retrieve analysis record for issue key: {issue_key}") record = db.query(JiraAnalysis).filter(JiraAnalysis.issue_key == issue_key).order_by(JiraAnalysis.created_at.desc()).first() if record: logger.debug(f"Found analysis record for {issue_key}: {record.id}") else: logger.debug(f"No analysis record found for {issue_key}") return record def update_record_status( db: Session, record_id: int, status: str, analysis_result: Optional[Dict[str, Any]] = None, error_message: Optional[str] = None, raw_response: Optional[Dict[str, Any]] = None, retry_count_increment: int = 0, last_processed_at: Optional[datetime] = None, next_retry_at: Optional[datetime] = None ) -> Optional[JiraAnalysis]: """Updates an existing Jira analysis record.""" db_analysis = db.query(JiraAnalysis).filter(JiraAnalysis.id == record_id).first() if db_analysis: db_analysis.status = status db_analysis.updated_at = datetime.now(timezone.utc) # Only update if not None, allowing explicit None to clear values # Always update these fields if provided, allowing explicit None to clear them db_analysis.analysis_result = analysis_result db_analysis.error_message = error_message db_analysis.raw_response = json.dumps(raw_response) if raw_response is not None else None if retry_count_increment > 0: db_analysis.retry_count += retry_count_increment db_analysis.last_processed_at = last_processed_at db_analysis.next_retry_at = next_retry_at # When status is set to "pending", clear relevant fields for retry if status == "pending": db_analysis.analysis_result = None db_analysis.error_message = None db_analysis.raw_response = None db_analysis.next_retry_at = None db.commit() db.refresh(db_analysis) return db_analysis def get_pending_analysis_records(db: Session) -> list[JiraAnalysis]: """Retrieves all pending or retrying analysis records that are ready for processing.""" now = datetime.now(timezone.utc) return db.query(JiraAnalysis).filter( (JiraAnalysis.status == "pending") | ((JiraAnalysis.status == "retrying") & (JiraAnalysis.next_retry_at <= now)) ).order_by(JiraAnalysis.created_at.asc()).all() def get_all_analysis_records(db: Session) -> list[JiraAnalysis]: """Retrieves all analysis records from the database.""" return db.query(JiraAnalysis).all() def get_analysis_by_id(db: Session, record_id: int) -> Optional[JiraAnalysis]: """Retrieves an analysis record by its unique database ID.""" return db.query(JiraAnalysis).filter(JiraAnalysis.id == record_id).first() def delete_all_analysis_records(db: Session) -> int: """Deletes all analysis records from the database and returns count of deleted records.""" count = db.query(JiraAnalysis).count() db.query(JiraAnalysis).delete() db.commit() return count db.query(JiraAnalysis).delete() db.commit() return count