Add role-based filtering and imporve code

This commit is contained in:
Urtzi Alfaro
2025-10-15 16:12:49 +02:00
parent 96ad5c6692
commit 8f9e9a7edc
158 changed files with 11033 additions and 1544 deletions

View File

@@ -38,10 +38,19 @@ async def cleanup_messaging():
async def publish_training_started(
job_id: str,
tenant_id: str,
total_products: int
total_products: int,
estimated_duration_minutes: Optional[int] = None,
estimated_completion_time: Optional[str] = None
) -> bool:
"""
Event 1: Training Started (0% progress)
Args:
job_id: Training job identifier
tenant_id: Tenant identifier
total_products: Number of products to train
estimated_duration_minutes: Estimated time to completion in minutes
estimated_completion_time: ISO timestamp of estimated completion
"""
event_data = {
"service_name": "training-service",
@@ -53,7 +62,10 @@ async def publish_training_started(
"progress": 0,
"current_step": "Training Started",
"step_details": f"Starting training for {total_products} products",
"total_products": total_products
"total_products": total_products,
"estimated_duration_minutes": estimated_duration_minutes,
"estimated_completion_time": estimated_completion_time,
"estimated_time_remaining_seconds": estimated_duration_minutes * 60 if estimated_duration_minutes else None
}
}
@@ -67,7 +79,8 @@ async def publish_training_started(
logger.info("Published training started event",
job_id=job_id,
tenant_id=tenant_id,
total_products=total_products)
total_products=total_products,
estimated_duration_minutes=estimated_duration_minutes)
else:
logger.error("Failed to publish training started event", job_id=job_id)
@@ -77,10 +90,17 @@ async def publish_training_started(
async def publish_data_analysis(
job_id: str,
tenant_id: str,
analysis_details: Optional[str] = None
analysis_details: Optional[str] = None,
estimated_time_remaining_seconds: Optional[int] = None
) -> bool:
"""
Event 2: Data Analysis (20% progress)
Args:
job_id: Training job identifier
tenant_id: Tenant identifier
analysis_details: Details about the analysis
estimated_time_remaining_seconds: Estimated time remaining in seconds
"""
event_data = {
"service_name": "training-service",
@@ -91,7 +111,8 @@ async def publish_data_analysis(
"tenant_id": tenant_id,
"progress": 20,
"current_step": "Data Analysis",
"step_details": analysis_details or "Analyzing sales, weather, and traffic data"
"step_details": analysis_details or "Analyzing sales, weather, and traffic data",
"estimated_time_remaining_seconds": estimated_time_remaining_seconds
}
}
@@ -116,7 +137,8 @@ async def publish_product_training_completed(
tenant_id: str,
product_name: str,
products_completed: int,
total_products: int
total_products: int,
estimated_time_remaining_seconds: Optional[int] = None
) -> bool:
"""
Event 3: Product Training Completed (contributes to 20-80% progress)
@@ -124,6 +146,14 @@ async def publish_product_training_completed(
This event is published each time a product training completes.
The frontend/consumer will calculate the progress as:
progress = 20 + (products_completed / total_products) * 60
Args:
job_id: Training job identifier
tenant_id: Tenant identifier
product_name: Name of the product that was trained
products_completed: Number of products completed so far
total_products: Total number of products
estimated_time_remaining_seconds: Estimated time remaining in seconds
"""
event_data = {
"service_name": "training-service",
@@ -136,7 +166,8 @@ async def publish_product_training_completed(
"products_completed": products_completed,
"total_products": total_products,
"current_step": "Model Training",
"step_details": f"Completed training for {product_name} ({products_completed}/{total_products})"
"step_details": f"Completed training for {product_name} ({products_completed}/{total_products})",
"estimated_time_remaining_seconds": estimated_time_remaining_seconds
}
}

View File

@@ -452,23 +452,50 @@ class EnhancedTrainingService:
try:
async with self.database_manager.get_session() as session:
await self._init_repositories(session)
log = await self.training_log_repo.get_log_by_job_id(job_id)
if not log:
return {"error": "Job not found"}
# Calculate estimated time remaining based on progress and elapsed time
estimated_time_remaining_seconds = None
if log.status == "running" and log.progress > 0 and log.start_time:
from datetime import datetime, timezone
elapsed_time = (datetime.now(timezone.utc) - log.start_time).total_seconds()
if elapsed_time > 0:
# Calculate estimated total time based on progress
estimated_total_time = (elapsed_time / log.progress) * 100
estimated_time_remaining_seconds = int(estimated_total_time - elapsed_time)
# Cap at reasonable maximum (e.g., 30 minutes)
estimated_time_remaining_seconds = min(estimated_time_remaining_seconds, 1800)
# Extract products info from results if available
products_total = 0
products_completed = 0
products_failed = 0
if log.results:
products_total = log.results.get("total_products", 0)
products_completed = log.results.get("successful_trainings", 0)
products_failed = log.results.get("failed_trainings", 0)
return {
"job_id": job_id,
"tenant_id": log.tenant_id,
"status": log.status,
"progress": log.progress,
"current_step": log.current_step,
"start_time": log.start_time.isoformat() if log.start_time else None,
"end_time": log.end_time.isoformat() if log.end_time else None,
"started_at": log.start_time.isoformat() if log.start_time else None,
"completed_at": log.end_time.isoformat() if log.end_time else None,
"error_message": log.error_message,
"results": log.results
"results": log.results,
"products_total": products_total,
"products_completed": products_completed,
"products_failed": products_failed,
"estimated_time_remaining_seconds": estimated_time_remaining_seconds,
"message": log.current_step
}
except Exception as e:
logger.error("Failed to get training status",
job_id=job_id,