Spaces:
Paused
Paused
File size: 7,639 Bytes
b70ff07 20adca1 b70ff07 20adca1 b70ff07 20adca1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete, func
from typing import Dict, Any, List
from datetime import datetime, timedelta
from ..core.dependencies import get_current_active_user, get_db
from ..db.database import get_db
from ..db.models import User, Order, Notification, Event
from ..utils.logger import logger
from ..services.maintenance import maintenance_service
from ..services.pos_analytics import pos_analytics
import asyncio
router = APIRouter()
@router.post("/sessions/cleanup")
async def cleanup_sessions(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, int]:
"""Manually trigger session cleanup"""
if "admin" not in current_user.roles:
raise HTTPException(
status_code=403,
detail="Only administrators can perform maintenance operations"
)
cutoff_date = datetime.utcnow() - timedelta(days=7)
stmt = delete(Event).where(Event.created_at < cutoff_date)
result = await db.execute(stmt)
await db.commit()
return {"deleted_sessions": result.rowcount}
@router.post("/data/archive")
async def archive_data(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, int]:
"""Manually trigger data archiving"""
if "admin" not in current_user.roles:
raise HTTPException(
status_code=403,
detail="Only administrators can perform maintenance operations"
)
archive_date = datetime.utcnow() - timedelta(days=365)
archived = {}
# Archive old orders
orders_stmt = delete(Order).where(
Order.created_at < archive_date,
Order.status.in_(["delivered", "cancelled"])
)
orders_result = await db.execute(orders_stmt)
archived["orders"] = orders_result.rowcount
# Archive old notifications
notif_stmt = delete(Notification).where(
Notification.created_at < archive_date,
Notification.read == True
)
notif_result = await db.execute(notif_stmt)
archived["notifications"] = notif_result.rowcount
await db.commit()
return archived
@router.get("/health")
async def check_health(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Check system health metrics"""
if "admin" not in current_user.roles:
raise HTTPException(
status_code=403,
detail="Only administrators can view system health"
)
try:
# Check database connection
await db.execute(select(1))
# Get database statistics
total_users = await db.scalar(select(func.count()).select_from(User))
total_orders = await db.scalar(select(func.count()).select_from(Order))
total_notifications = await db.scalar(select(func.count()).select_from(Notification))
return {
"status": "healthy",
"timestamp": datetime.utcnow(),
"database": {
"connected": True,
"total_users": total_users,
"total_orders": total_orders,
"total_notifications": total_notifications
}
}
except Exception as e:
logger.error(f"Health check error: {str(e)}")
return {
"status": "unhealthy",
"error": str(e),
"timestamp": datetime.utcnow()
}
@router.post("/database/maintenance")
async def perform_db_maintenance(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Manually trigger database maintenance"""
if "admin" not in current_user.roles:
raise HTTPException(
status_code=403,
detail="Only administrators can perform maintenance operations"
)
try:
# Cleanup expired sessions
await cleanup_sessions(current_user, db)
# Run VACUUM ANALYZE (requires raw SQL)
await db.execute("VACUUM ANALYZE;")
return {
"status": "success",
"message": "Database maintenance completed successfully"
}
except Exception as e:
logger.error(f"Database maintenance error: {str(e)}")
raise HTTPException(
status_code=500,
detail=f"Database maintenance failed: {str(e)}"
)
@router.get("/health")
async def health_check() -> Dict[str, Any]:
"""Public health check endpoint that doesn't require authentication"""
return {
"status": "healthy",
"timestamp": maintenance_service.get_timestamp()
}
@router.get("/system-status")
async def get_system_status(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Get detailed system status including POS integration health"""
if not current_user.is_superuser:
raise HTTPException(
status_code=403,
detail="Only superusers can access system status"
)
# Check database connectivity
db_status = await maintenance_service.check_database()
# Check POS integration
pos_status = await pos_analytics.health_check()
# Check Redis connectivity
redis_status = await maintenance_service.check_redis()
# Check background tasks
tasks_status = await maintenance_service.check_background_tasks()
return {
"status": "healthy",
"timestamp": maintenance_service.get_timestamp(),
"components": {
"database": db_status,
"redis": redis_status,
"background_tasks": tasks_status,
"pos_integration": pos_status
}
}
@router.post("/sync/pos-metrics")
async def trigger_pos_sync(
current_user: User = Depends(get_current_active_user)
) -> Dict[str, Any]:
"""Manually trigger POS metrics synchronization"""
if not current_user.is_superuser:
raise HTTPException(
status_code=403,
detail="Only superusers can trigger manual sync"
)
try:
success = await pos_analytics.sync_all_metrics()
return {
"status": "success" if success else "partial_failure",
"message": "POS metrics sync completed successfully" if success else "Some metrics failed to sync"
}
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Failed to sync POS metrics: {str(e)}"
)
@router.get("/sync/status")
async def get_sync_status(
current_user: User = Depends(get_current_active_user)
) -> Dict[str, Any]:
"""Get status of background sync tasks"""
if not current_user.is_superuser:
raise HTTPException(
status_code=403,
detail="Only superusers can view sync status"
)
tasks_status = await maintenance_service.check_background_tasks()
pos_health = await pos_analytics.health_check()
return {
"background_tasks": tasks_status,
"pos_integration": pos_health,
"last_sync_timestamp": maintenance_service.get_last_sync_time(),
"next_sync_due": maintenance_service.get_next_sync_time()
} |