Improve the frontend 3
This commit is contained in:
0
services/orchestrator/app/repositories/__init__.py
Normal file
0
services/orchestrator/app/repositories/__init__.py
Normal file
@@ -0,0 +1,175 @@
|
||||
# ================================================================
|
||||
# services/orchestrator/app/repositories/orchestration_run_repository.py
|
||||
# ================================================================
|
||||
"""
|
||||
Orchestration Run Repository - Database operations for orchestration audit trail
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime, date
|
||||
from typing import List, Optional, Dict, Any
|
||||
from sqlalchemy import select, and_, desc, func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.orchestration_run import OrchestrationRun, OrchestrationStatus
|
||||
|
||||
|
||||
class OrchestrationRunRepository:
|
||||
"""Repository for orchestration run operations"""
|
||||
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def create_run(self, run_data: Dict[str, Any]) -> OrchestrationRun:
|
||||
"""Create a new orchestration run"""
|
||||
run = OrchestrationRun(**run_data)
|
||||
self.db.add(run)
|
||||
await self.db.flush()
|
||||
return run
|
||||
|
||||
async def get_run_by_id(self, run_id: uuid.UUID) -> Optional[OrchestrationRun]:
|
||||
"""Get orchestration run by ID"""
|
||||
stmt = select(OrchestrationRun).where(OrchestrationRun.id == run_id)
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def update_run(self, run_id: uuid.UUID, updates: Dict[str, Any]) -> Optional[OrchestrationRun]:
|
||||
"""Update orchestration run"""
|
||||
run = await self.get_run_by_id(run_id)
|
||||
if not run:
|
||||
return None
|
||||
|
||||
for key, value in updates.items():
|
||||
if hasattr(run, key):
|
||||
setattr(run, key, value)
|
||||
|
||||
run.updated_at = datetime.utcnow()
|
||||
await self.db.flush()
|
||||
return run
|
||||
|
||||
async def list_runs(
|
||||
self,
|
||||
tenant_id: Optional[uuid.UUID] = None,
|
||||
status: Optional[OrchestrationStatus] = None,
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None,
|
||||
limit: int = 50,
|
||||
offset: int = 0
|
||||
) -> List[OrchestrationRun]:
|
||||
"""List orchestration runs with filters"""
|
||||
conditions = []
|
||||
|
||||
if tenant_id:
|
||||
conditions.append(OrchestrationRun.tenant_id == tenant_id)
|
||||
if status:
|
||||
conditions.append(OrchestrationRun.status == status)
|
||||
if start_date:
|
||||
conditions.append(func.date(OrchestrationRun.started_at) >= start_date)
|
||||
if end_date:
|
||||
conditions.append(func.date(OrchestrationRun.started_at) <= end_date)
|
||||
|
||||
stmt = (
|
||||
select(OrchestrationRun)
|
||||
.where(and_(*conditions) if conditions else True)
|
||||
.order_by(desc(OrchestrationRun.started_at))
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
)
|
||||
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalars().all()
|
||||
|
||||
async def get_latest_run_for_tenant(self, tenant_id: uuid.UUID) -> Optional[OrchestrationRun]:
|
||||
"""Get the most recent orchestration run for a tenant"""
|
||||
stmt = (
|
||||
select(OrchestrationRun)
|
||||
.where(OrchestrationRun.tenant_id == tenant_id)
|
||||
.order_by(desc(OrchestrationRun.started_at))
|
||||
.limit(1)
|
||||
)
|
||||
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def generate_run_number(self) -> str:
|
||||
"""Generate unique run number"""
|
||||
today = date.today()
|
||||
date_str = today.strftime("%Y%m%d")
|
||||
|
||||
# Count existing runs for today
|
||||
stmt = select(func.count(OrchestrationRun.id)).where(
|
||||
func.date(OrchestrationRun.started_at) == today
|
||||
)
|
||||
result = await self.db.execute(stmt)
|
||||
count = result.scalar() or 0
|
||||
|
||||
return f"ORCH-{date_str}-{count + 1:04d}"
|
||||
|
||||
async def get_failed_runs(self, limit: int = 10) -> List[OrchestrationRun]:
|
||||
"""Get recent failed orchestration runs"""
|
||||
stmt = (
|
||||
select(OrchestrationRun)
|
||||
.where(OrchestrationRun.status == OrchestrationStatus.failed)
|
||||
.order_by(desc(OrchestrationRun.started_at))
|
||||
.limit(limit)
|
||||
)
|
||||
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalars().all()
|
||||
|
||||
async def get_run_statistics(
|
||||
self,
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Get orchestration run statistics"""
|
||||
conditions = []
|
||||
if start_date:
|
||||
conditions.append(func.date(OrchestrationRun.started_at) >= start_date)
|
||||
if end_date:
|
||||
conditions.append(func.date(OrchestrationRun.started_at) <= end_date)
|
||||
|
||||
where_clause = and_(*conditions) if conditions else True
|
||||
|
||||
# Total runs
|
||||
total_stmt = select(func.count(OrchestrationRun.id)).where(where_clause)
|
||||
total_result = await self.db.execute(total_stmt)
|
||||
total_runs = total_result.scalar() or 0
|
||||
|
||||
# Successful runs
|
||||
success_stmt = select(func.count(OrchestrationRun.id)).where(
|
||||
and_(
|
||||
where_clause,
|
||||
OrchestrationRun.status == OrchestrationStatus.completed
|
||||
)
|
||||
)
|
||||
success_result = await self.db.execute(success_stmt)
|
||||
successful_runs = success_result.scalar() or 0
|
||||
|
||||
# Failed runs
|
||||
failed_stmt = select(func.count(OrchestrationRun.id)).where(
|
||||
and_(
|
||||
where_clause,
|
||||
OrchestrationRun.status == OrchestrationStatus.failed
|
||||
)
|
||||
)
|
||||
failed_result = await self.db.execute(failed_stmt)
|
||||
failed_runs = failed_result.scalar() or 0
|
||||
|
||||
# Average duration
|
||||
avg_duration_stmt = select(func.avg(OrchestrationRun.duration_seconds)).where(
|
||||
and_(
|
||||
where_clause,
|
||||
OrchestrationRun.status == OrchestrationStatus.completed
|
||||
)
|
||||
)
|
||||
avg_duration_result = await self.db.execute(avg_duration_stmt)
|
||||
avg_duration = avg_duration_result.scalar() or 0
|
||||
|
||||
return {
|
||||
'total_runs': total_runs,
|
||||
'successful_runs': successful_runs,
|
||||
'failed_runs': failed_runs,
|
||||
'success_rate': (successful_runs / total_runs * 100) if total_runs > 0 else 0,
|
||||
'average_duration_seconds': float(avg_duration) if avg_duration else 0
|
||||
}
|
||||
Reference in New Issue
Block a user