Files
bakery-ia/services/training/app/api/training.py

621 lines
22 KiB
Python
Raw Normal View History

2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
Enhanced Training API Endpoints with Repository Pattern
Updated to use repository pattern with dependency injection and improved error handling
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks, Request
2025-07-28 19:28:39 +02:00
from fastapi import Query, Path
2025-07-20 07:24:04 +02:00
from typing import List, Optional, Dict, Any
import structlog
2025-08-01 16:26:36 +02:00
from datetime import datetime, timezone
import uuid
2025-08-08 09:08:41 +02:00
from app.services.training_service import EnhancedTrainingService
2025-07-19 16:59:37 +02:00
from app.schemas.training import (
2025-07-20 07:24:04 +02:00
TrainingJobRequest,
2025-08-08 09:08:41 +02:00
SingleProductTrainingRequest,
2025-07-28 19:28:39 +02:00
TrainingJobResponse
2025-07-20 07:24:04 +02:00
)
2025-08-01 16:26:36 +02:00
from app.services.messaging import (
publish_job_progress,
publish_data_validation_started,
publish_data_validation_completed,
publish_job_step_completed,
publish_job_completed,
publish_job_failed,
publish_job_started
)
2025-08-02 17:09:53 +02:00
from shared.auth.decorators import require_admin_role, get_current_user_dep, get_current_tenant_id_dep
2025-08-08 09:08:41 +02:00
from shared.database.base import create_database_manager
from shared.monitoring.decorators import track_execution_time
from shared.monitoring.metrics import get_metrics_collector
from app.core.config import settings
2025-07-20 07:24:04 +02:00
logger = structlog.get_logger()
2025-08-08 09:08:41 +02:00
router = APIRouter(tags=["enhanced-training"])
def get_enhanced_training_service():
"""Dependency injection for EnhancedTrainingService"""
database_manager = create_database_manager(settings.DATABASE_URL, "training-service")
return EnhancedTrainingService(database_manager)
2025-07-26 23:34:46 +02:00
@router.post("/tenants/{tenant_id}/training/jobs", response_model=TrainingJobResponse)
2025-08-08 09:08:41 +02:00
@track_execution_time("enhanced_training_job_duration_seconds", "training-service")
async def start_enhanced_training_job(
2025-07-19 16:59:37 +02:00
request: TrainingJobRequest,
2025-07-28 19:28:39 +02:00
tenant_id: str = Path(..., description="Tenant ID"),
background_tasks: BackgroundTasks = BackgroundTasks(),
2025-08-08 09:08:41 +02:00
request_obj: Request = None,
2025-07-28 19:28:39 +02:00
current_tenant: str = Depends(get_current_tenant_id_dep),
2025-08-08 09:08:41 +02:00
enhanced_training_service: EnhancedTrainingService = Depends(get_enhanced_training_service)
):
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
Start a new enhanced training job for all tenant products using repository pattern.
2025-07-28 19:28:39 +02:00
2025-08-08 09:08:41 +02:00
🚀 ENHANCED IMMEDIATE RESPONSE PATTERN:
1. Validate request with enhanced validation
2. Create job record using repository pattern
3. Return 200 with enhanced job details
4. Execute enhanced training in background with repository tracking
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
Enhanced features:
- Repository pattern for data access
- Enhanced error handling and logging
- Metrics tracking and monitoring
- Transactional operations
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
metrics = get_metrics_collector(request_obj)
try:
2025-08-08 09:08:41 +02:00
# Enhanced tenant validation
2025-07-28 19:28:39 +02:00
if tenant_id != current_tenant:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_training_access_denied_total")
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant resources"
2025-07-20 07:24:04 +02:00
)
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
# Generate enhanced job ID
job_id = f"enhanced_training_{tenant_id}_{uuid.uuid4().hex[:8]}"
2025-07-27 10:30:42 +02:00
2025-08-08 09:08:41 +02:00
logger.info("Creating enhanced training job using repository pattern",
job_id=job_id,
tenant_id=tenant_id)
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
# Record job creation metrics
if metrics:
metrics.increment_counter("enhanced_training_jobs_created_total")
# Add enhanced background task
2025-08-01 16:26:36 +02:00
background_tasks.add_task(
2025-08-08 09:08:41 +02:00
execute_enhanced_training_job_background,
2025-07-28 19:28:39 +02:00
tenant_id=tenant_id,
2025-08-01 16:26:36 +02:00
job_id=job_id,
bakery_location=(40.4168, -3.7038),
requested_start=request.start_date,
requested_end=request.end_date
)
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
# Return enhanced immediate success response
2025-08-01 16:26:36 +02:00
response_data = {
"job_id": job_id,
"tenant_id": tenant_id,
2025-08-08 09:08:41 +02:00
"status": "pending",
"message": "Enhanced training job started successfully using repository pattern",
2025-08-01 16:26:36 +02:00
"created_at": datetime.now(timezone.utc),
2025-08-08 09:08:41 +02:00
"estimated_duration_minutes": 18,
2025-08-01 16:26:36 +02:00
"training_results": {
2025-08-08 09:08:41 +02:00
"total_products": 0, # Will be updated during processing
2025-08-01 16:26:36 +02:00
"successful_trainings": 0,
"failed_trainings": 0,
"products": [],
"overall_training_time_seconds": 0.0
},
"data_summary": None,
"completed_at": None,
"error_details": None,
"processing_metadata": {
"background_task": True,
2025-08-08 09:08:41 +02:00
"async_execution": True,
"enhanced_features": True,
"repository_pattern": True,
"dependency_injection": True
2025-08-01 16:26:36 +02:00
}
}
2025-08-08 09:08:41 +02:00
logger.info("Enhanced training job queued successfully",
job_id=job_id,
features=["repository-pattern", "dependency-injection", "enhanced-tracking"])
2025-08-01 16:26:36 +02:00
return TrainingJobResponse(**response_data)
except HTTPException:
# Re-raise HTTP exceptions as-is
raise
2025-07-28 19:28:39 +02:00
except ValueError as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_training_validation_errors_total")
logger.error("Enhanced training job validation error",
error=str(e),
tenant_id=tenant_id)
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
2025-07-27 22:58:18 +02:00
)
except Exception as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_training_job_errors_total")
logger.error("Failed to queue enhanced training job",
error=str(e),
tenant_id=tenant_id)
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-08-08 09:08:41 +02:00
detail="Failed to start enhanced training job"
2025-07-28 19:28:39 +02:00
)
2025-07-19 16:59:37 +02:00
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
async def execute_enhanced_training_job_background(
2025-08-01 16:26:36 +02:00
tenant_id: str,
job_id: str,
bakery_location: tuple,
requested_start: Optional[datetime] = None,
requested_end: Optional[datetime] = None
):
"""
2025-08-08 09:08:41 +02:00
Enhanced background task that executes the training job using repository pattern.
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
🔧 ENHANCED FEATURES:
- Repository pattern for all data operations
- Enhanced error handling with structured logging
- Transactional operations for data consistency
- Comprehensive metrics tracking
- Database connection pooling
- Enhanced progress reporting
2025-08-01 16:26:36 +02:00
"""
2025-08-08 09:08:41 +02:00
logger.info("Enhanced background training job started",
job_id=job_id,
tenant_id=tenant_id,
features=["repository-pattern", "enhanced-tracking"])
2025-08-01 16:26:36 +02:00
2025-08-08 09:08:41 +02:00
# Get enhanced training service with dependency injection
database_manager = create_database_manager(settings.DATABASE_URL, "training-service")
enhanced_training_service = EnhancedTrainingService(database_manager)
try:
# Publish job started event
await publish_job_started(job_id, tenant_id, {
"enhanced_features": True,
"repository_pattern": True,
"job_type": "enhanced_training"
})
training_config = {
"job_id": job_id,
"tenant_id": tenant_id,
"bakery_location": {
"latitude": bakery_location[0],
"longitude": bakery_location[1]
},
"requested_start": requested_start.isoformat() if requested_start else None,
"requested_end": requested_end.isoformat() if requested_end else None,
"estimated_duration_minutes": 18,
"background_execution": True,
"enhanced_features": True,
"repository_pattern": True,
"api_version": "enhanced_v1"
}
# Update job status using repository pattern
await enhanced_training_service._update_job_status_repository(
job_id=job_id,
status="running",
progress=0,
current_step="Initializing enhanced training pipeline"
)
# Execute the enhanced training pipeline with repository pattern
result = await enhanced_training_service.start_training_job(
tenant_id=tenant_id,
job_id=job_id,
bakery_location=bakery_location,
requested_start=requested_start,
requested_end=requested_end
)
# Update final status using repository pattern
await enhanced_training_service._update_job_status_repository(
job_id=job_id,
status="completed",
progress=100,
current_step="Enhanced training completed successfully",
results=result
)
# Publish enhanced completion event
await publish_job_completed(
job_id=job_id,
tenant_id=tenant_id,
results={
**result,
"enhanced_features": True,
"repository_integration": True
}
)
logger.info("Enhanced background training job completed successfully",
job_id=job_id,
models_created=result.get('products_trained', 0),
features=["repository-pattern", "enhanced-tracking"])
except Exception as training_error:
logger.error("Enhanced training pipeline failed",
2025-08-03 14:55:13 +02:00
job_id=job_id,
2025-08-08 09:08:41 +02:00
error=str(training_error))
try:
await enhanced_training_service._update_job_status_repository(
job_id=job_id,
status="failed",
progress=0,
current_step="Enhanced training failed",
error_message=str(training_error)
)
except Exception as status_error:
logger.error("Failed to update job status after training error",
job_id=job_id,
status_error=str(status_error))
# Publish enhanced failure event
await publish_job_failed(
job_id=job_id,
tenant_id=tenant_id,
error=str(training_error),
metadata={
"enhanced_features": True,
"repository_pattern": True,
"error_type": type(training_error).__name__
}
)
except Exception as background_error:
logger.error("Critical error in enhanced background training job",
2025-08-01 16:26:36 +02:00
job_id=job_id,
2025-08-08 09:08:41 +02:00
error=str(background_error))
finally:
logger.info("Enhanced background training job cleanup completed",
job_id=job_id)
2025-08-01 16:26:36 +02:00
2025-08-14 16:47:34 +02:00
@router.post("/tenants/{tenant_id}/training/products/{inventory_product_id}", response_model=TrainingJobResponse)
2025-08-08 09:08:41 +02:00
@track_execution_time("enhanced_single_product_training_duration_seconds", "training-service")
async def start_enhanced_single_product_training(
2025-07-19 16:59:37 +02:00
request: SingleProductTrainingRequest,
2025-07-28 19:28:39 +02:00
tenant_id: str = Path(..., description="Tenant ID"),
2025-08-14 16:47:34 +02:00
inventory_product_id: str = Path(..., description="Inventory product UUID"),
2025-08-08 09:08:41 +02:00
request_obj: Request = None,
2025-07-28 19:28:39 +02:00
current_tenant: str = Depends(get_current_tenant_id_dep),
2025-08-08 09:08:41 +02:00
enhanced_training_service: EnhancedTrainingService = Depends(get_enhanced_training_service)
2025-07-19 16:59:37 +02:00
):
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
Start enhanced training for a single product using repository pattern.
2025-07-28 19:28:39 +02:00
2025-08-08 09:08:41 +02:00
Enhanced features:
- Repository pattern for data access
- Enhanced error handling and validation
- Metrics tracking
- Transactional operations
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
metrics = get_metrics_collector(request_obj)
2025-08-02 17:09:53 +02:00
2025-07-19 16:59:37 +02:00
try:
2025-08-08 09:08:41 +02:00
# Enhanced tenant validation
2025-07-28 19:28:39 +02:00
if tenant_id != current_tenant:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_single_product_access_denied_total")
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant resources"
2025-07-20 07:24:04 +02:00
)
2025-08-08 09:08:41 +02:00
logger.info("Starting enhanced single product training",
2025-08-14 16:47:34 +02:00
inventory_product_id=inventory_product_id,
2025-08-08 09:08:41 +02:00
tenant_id=tenant_id)
# Record metrics
if metrics:
metrics.increment_counter("enhanced_single_product_training_total")
# Generate enhanced job ID
2025-08-14 16:47:34 +02:00
job_id = f"enhanced_single_{tenant_id}_{inventory_product_id}_{uuid.uuid4().hex[:8]}"
2025-07-19 16:59:37 +02:00
2025-08-08 09:08:41 +02:00
# Delegate to enhanced training service (single product method to be implemented)
result = await enhanced_training_service.start_single_product_training(
2025-07-19 16:59:37 +02:00
tenant_id=tenant_id,
2025-08-14 16:47:34 +02:00
inventory_product_id=inventory_product_id,
2025-08-08 09:08:41 +02:00
job_id=job_id,
bakery_location=request.bakery_location or (40.4168, -3.7038)
2025-07-19 16:59:37 +02:00
)
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_single_product_training_success_total")
logger.info("Enhanced single product training completed",
2025-08-14 16:47:34 +02:00
inventory_product_id=inventory_product_id,
2025-08-08 09:08:41 +02:00
job_id=job_id)
2025-07-28 19:28:39 +02:00
return TrainingJobResponse(**result)
2025-07-20 07:24:04 +02:00
2025-07-28 19:28:39 +02:00
except ValueError as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_single_product_validation_errors_total")
logger.error("Enhanced single product training validation error",
error=str(e),
2025-08-14 16:47:34 +02:00
inventory_product_id=inventory_product_id)
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
2025-07-19 16:59:37 +02:00
except Exception as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_single_product_training_errors_total")
logger.error("Enhanced single product training failed",
error=str(e),
2025-08-14 16:47:34 +02:00
inventory_product_id=inventory_product_id)
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-08-08 09:08:41 +02:00
detail="Enhanced single product training failed"
2025-07-28 19:28:39 +02:00
)
2025-07-19 16:59:37 +02:00
2025-08-08 09:08:41 +02:00
@router.get("/tenants/{tenant_id}/training/jobs/{job_id}/status")
@track_execution_time("enhanced_job_status_duration_seconds", "training-service")
async def get_enhanced_training_job_status(
2025-07-28 19:28:39 +02:00
tenant_id: str = Path(..., description="Tenant ID"),
job_id: str = Path(..., description="Job ID"),
2025-08-08 09:08:41 +02:00
request_obj: Request = None,
2025-07-28 19:28:39 +02:00
current_tenant: str = Depends(get_current_tenant_id_dep),
2025-08-08 09:08:41 +02:00
enhanced_training_service: EnhancedTrainingService = Depends(get_enhanced_training_service)
2025-07-19 16:59:37 +02:00
):
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
Get enhanced training job status using repository pattern.
2025-07-28 19:28:39 +02:00
"""
2025-08-08 09:08:41 +02:00
metrics = get_metrics_collector(request_obj)
2025-07-19 16:59:37 +02:00
try:
2025-07-28 19:28:39 +02:00
# Validate tenant access
if tenant_id != current_tenant:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_status_access_denied_total")
2025-07-20 07:24:04 +02:00
raise HTTPException(
2025-07-28 19:28:39 +02:00
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant resources"
2025-07-20 07:24:04 +02:00
)
2025-08-08 09:08:41 +02:00
# Get status using enhanced service
status_info = await enhanced_training_service.get_training_status(job_id)
if not status_info or status_info.get("error"):
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Training job not found"
)
if metrics:
metrics.increment_counter("enhanced_status_requests_total")
2025-07-28 19:28:39 +02:00
return {
2025-08-08 09:08:41 +02:00
**status_info,
"enhanced_features": True,
"repository_integration": True
2025-07-28 19:28:39 +02:00
}
2025-07-20 07:24:04 +02:00
2025-08-08 09:08:41 +02:00
except HTTPException:
raise
2025-07-19 16:59:37 +02:00
except Exception as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_status_errors_total")
logger.error("Failed to get enhanced training status",
job_id=job_id,
error=str(e))
2025-07-28 19:28:39 +02:00
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-08-08 09:08:41 +02:00
detail="Failed to get training status"
2025-07-28 19:28:39 +02:00
)
2025-07-27 22:58:18 +02:00
2025-08-02 17:09:53 +02:00
2025-08-08 09:08:41 +02:00
@router.get("/tenants/{tenant_id}/models")
@track_execution_time("enhanced_models_list_duration_seconds", "training-service")
async def get_enhanced_tenant_models(
tenant_id: str = Path(..., description="Tenant ID"),
active_only: bool = Query(True, description="Return only active models"),
skip: int = Query(0, description="Number of models to skip"),
limit: int = Query(100, description="Number of models to return"),
request_obj: Request = None,
current_tenant: str = Depends(get_current_tenant_id_dep),
enhanced_training_service: EnhancedTrainingService = Depends(get_enhanced_training_service)
2025-08-02 17:09:53 +02:00
):
2025-08-08 09:08:41 +02:00
"""
Get tenant models using enhanced repository pattern.
"""
metrics = get_metrics_collector(request_obj)
2025-08-02 17:09:53 +02:00
try:
2025-08-08 09:08:41 +02:00
# Validate tenant access
if tenant_id != current_tenant:
if metrics:
metrics.increment_counter("enhanced_models_access_denied_total")
2025-08-02 17:09:53 +02:00
raise HTTPException(
2025-08-08 09:08:41 +02:00
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant resources"
2025-08-02 17:09:53 +02:00
)
2025-08-08 09:08:41 +02:00
# Get models using enhanced service
models = await enhanced_training_service.get_tenant_models(
tenant_id=tenant_id,
active_only=active_only,
skip=skip,
limit=limit
2025-08-02 17:09:53 +02:00
)
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_models_requests_total")
return {
2025-08-02 17:09:53 +02:00
"tenant_id": tenant_id,
2025-08-08 09:08:41 +02:00
"models": models,
"total_returned": len(models),
"active_only": active_only,
"pagination": {
"skip": skip,
"limit": limit
},
"enhanced_features": True,
"repository_integration": True
2025-08-02 17:09:53 +02:00
}
except Exception as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_models_errors_total")
logger.error("Failed to get enhanced tenant models",
tenant_id=tenant_id,
2025-08-02 17:09:53 +02:00
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-08-08 09:08:41 +02:00
detail="Failed to get tenant models"
2025-08-02 17:09:53 +02:00
)
2025-08-08 09:08:41 +02:00
@router.get("/tenants/{tenant_id}/models/{model_id}/performance")
@track_execution_time("enhanced_model_performance_duration_seconds", "training-service")
async def get_enhanced_model_performance(
tenant_id: str = Path(..., description="Tenant ID"),
model_id: str = Path(..., description="Model ID"),
request_obj: Request = None,
current_tenant: str = Depends(get_current_tenant_id_dep),
enhanced_training_service: EnhancedTrainingService = Depends(get_enhanced_training_service)
2025-08-02 17:09:53 +02:00
):
2025-08-08 09:08:41 +02:00
"""
Get enhanced model performance metrics using repository pattern.
"""
metrics = get_metrics_collector(request_obj)
2025-08-02 17:09:53 +02:00
try:
2025-08-08 09:08:41 +02:00
# Validate tenant access
if tenant_id != current_tenant:
if metrics:
metrics.increment_counter("enhanced_performance_access_denied_total")
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant resources"
)
2025-08-02 17:09:53 +02:00
2025-08-08 09:08:41 +02:00
# Get performance using enhanced service
performance = await enhanced_training_service.get_model_performance(model_id)
if not performance:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Model performance not found"
)
if metrics:
metrics.increment_counter("enhanced_performance_requests_total")
2025-08-02 17:09:53 +02:00
return {
2025-08-08 09:08:41 +02:00
**performance,
"enhanced_features": True,
"repository_integration": True
2025-08-02 17:09:53 +02:00
}
2025-08-08 09:08:41 +02:00
except HTTPException:
raise
2025-08-02 17:09:53 +02:00
except Exception as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_performance_errors_total")
logger.error("Failed to get enhanced model performance",
model_id=model_id,
2025-08-02 17:09:53 +02:00
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-08-08 09:08:41 +02:00
detail="Failed to get model performance"
2025-08-02 17:09:53 +02:00
)
2025-08-08 09:08:41 +02:00
@router.get("/tenants/{tenant_id}/statistics")
@track_execution_time("enhanced_tenant_statistics_duration_seconds", "training-service")
async def get_enhanced_tenant_statistics(
tenant_id: str = Path(..., description="Tenant ID"),
request_obj: Request = None,
current_tenant: str = Depends(get_current_tenant_id_dep),
enhanced_training_service: EnhancedTrainingService = Depends(get_enhanced_training_service)
2025-08-02 17:09:53 +02:00
):
2025-08-08 09:08:41 +02:00
"""
Get comprehensive enhanced tenant statistics using repository pattern.
"""
metrics = get_metrics_collector(request_obj)
2025-08-02 17:09:53 +02:00
try:
2025-08-08 09:08:41 +02:00
# Validate tenant access
if tenant_id != current_tenant:
if metrics:
metrics.increment_counter("enhanced_statistics_access_denied_total")
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant resources"
)
2025-08-02 17:09:53 +02:00
2025-08-08 09:08:41 +02:00
# Get statistics using enhanced service
statistics = await enhanced_training_service.get_tenant_statistics(tenant_id)
2025-08-02 17:09:53 +02:00
2025-08-08 09:08:41 +02:00
if statistics.get("error"):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=statistics["error"]
)
if metrics:
metrics.increment_counter("enhanced_statistics_requests_total")
2025-08-02 17:09:53 +02:00
return {
2025-08-08 09:08:41 +02:00
**statistics,
"enhanced_features": True,
"repository_integration": True
2025-08-02 17:09:53 +02:00
}
2025-08-08 09:08:41 +02:00
except HTTPException:
raise
2025-08-02 17:09:53 +02:00
except Exception as e:
2025-08-08 09:08:41 +02:00
if metrics:
metrics.increment_counter("enhanced_statistics_errors_total")
logger.error("Failed to get enhanced tenant statistics",
tenant_id=tenant_id,
2025-08-02 17:09:53 +02:00
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-08-08 09:08:41 +02:00
detail="Failed to get tenant statistics"
)
@router.get("/health")
async def enhanced_health_check():
"""
Enhanced health check endpoint for the training service.
"""
return {
"status": "healthy",
"service": "enhanced-training-service",
"version": "2.0.0",
"features": [
"repository-pattern",
"dependency-injection",
"enhanced-error-handling",
"metrics-tracking",
"transactional-operations"
],
"timestamp": datetime.now().isoformat()
}