demo seed change

This commit is contained in:
Urtzi Alfaro
2025-12-13 23:57:54 +01:00
parent f3688dfb04
commit ff830a3415
299 changed files with 20328 additions and 19485 deletions

View File

@@ -25,10 +25,17 @@ route_builder = RouteBuilder('demo')
async def _background_cloning_task(session_id: str, session_obj_id: UUID, base_tenant_id: str):
"""Background task for orchestrated cloning - creates its own DB session"""
from app.core.database import db_manager
from app.models import DemoSession
from sqlalchemy import select
from app.models import DemoSession, DemoSessionStatus
from sqlalchemy import select, update
from app.core.redis_wrapper import get_redis
logger.info(
"Starting background cloning task",
session_id=session_id,
session_obj_id=str(session_obj_id),
base_tenant_id=base_tenant_id
)
# Create new database session for background task
async with db_manager.session_factory() as db:
try:
@@ -43,8 +50,30 @@ async def _background_cloning_task(session_id: str, session_obj_id: UUID, base_t
if not session:
logger.error("Session not found for cloning", session_id=session_id)
# Mark session as failed in Redis for frontend polling
try:
client = await redis.get_client()
status_key = f"session:{session_id}:status"
import json
status_data = {
"session_id": session_id,
"status": "failed",
"error": "Session not found in database",
"progress": {},
"total_records_cloned": 0
}
await client.setex(status_key, 7200, json.dumps(status_data))
except Exception as redis_error:
logger.error("Failed to update Redis status for missing session", error=str(redis_error))
return
logger.info(
"Found session for cloning",
session_id=session_id,
current_status=session.status.value,
demo_account_type=session.demo_account_type
)
# Create session manager with new DB session
session_manager = DemoSessionManager(db, redis)
await session_manager.trigger_orchestrated_cloning(session, base_tenant_id)
@@ -58,25 +87,40 @@ async def _background_cloning_task(session_id: str, session_obj_id: UUID, base_t
)
# Attempt to update session status to failed if possible
try:
from app.core.database import db_manager
from app.models import DemoSession
from sqlalchemy import select, update
# Try to update the session directly in DB to mark it as failed
async with db_manager.session_factory() as update_db:
from app.models import DemoSessionStatus
update_result = await update_db.execute(
update(DemoSession)
.where(DemoSession.id == session_obj_id)
.values(status=DemoSessionStatus.FAILED, cloning_completed_at=datetime.now(timezone.utc))
)
await update_db.commit()
logger.info("Successfully updated session status to FAILED in database")
except Exception as update_error:
logger.error(
"Failed to update session status to FAILED after background task error",
session_id=session_id,
error=str(update_error)
)
# Also update Redis status for frontend polling
try:
client = await redis.get_client()
status_key = f"session:{session_id}:status"
import json
status_data = {
"session_id": session_id,
"status": "failed",
"error": str(e),
"progress": {},
"total_records_cloned": 0,
"cloning_completed_at": datetime.now(timezone.utc).isoformat()
}
await client.setex(status_key, 7200, json.dumps(status_data))
logger.info("Successfully updated Redis status to FAILED")
except Exception as redis_error:
logger.error("Failed to update Redis status after background task error", error=str(redis_error))
def _handle_task_result(task, session_id: str):
@@ -91,6 +135,36 @@ def _handle_task_result(task, session_id: str):
error=str(e),
exc_info=True
)
# Try to update Redis status to reflect the failure
try:
from app.core.redis_wrapper import get_redis
import json
async def update_redis_status():
redis = await get_redis()
client = await redis.get_client()
status_key = f"session:{session_id}:status"
status_data = {
"session_id": session_id,
"status": "failed",
"error": f"Task exception: {str(e)}",
"progress": {},
"total_records_cloned": 0,
"cloning_completed_at": datetime.now(timezone.utc).isoformat()
}
await client.setex(status_key, 7200, json.dumps(status_data))
# Run the async function
import asyncio
asyncio.run(update_redis_status())
except Exception as redis_error:
logger.error(
"Failed to update Redis status in task result handler",
session_id=session_id,
error=str(redis_error)
)
@router.post(
@@ -209,6 +283,123 @@ async def get_session_status(
return status
@router.get(
route_builder.build_resource_detail_route("sessions", "session_id", include_tenant_prefix=False) + "/errors",
response_model=dict
)
async def get_session_errors(
session_id: str = Path(...),
db: AsyncSession = Depends(get_db),
redis: DemoRedisWrapper = Depends(get_redis)
):
"""
Get detailed error information for a failed demo session
Returns comprehensive error details including:
- Failed services and their specific errors
- Network connectivity issues
- Timeout problems
- Service-specific error messages
"""
try:
# Try to get the session first
session_manager = DemoSessionManager(db, redis)
session = await session_manager.get_session(session_id)
if not session:
raise HTTPException(status_code=404, detail="Session not found")
# Check if session has failed status
if session.status != DemoSessionStatus.FAILED:
return {
"session_id": session_id,
"status": session.status.value,
"has_errors": False,
"message": "Session has not failed - no error details available"
}
# Get detailed error information from cloning progress
error_details = []
failed_services = []
if session.cloning_progress:
for service_name, service_data in session.cloning_progress.items():
if isinstance(service_data, dict) and service_data.get("status") == "failed":
failed_services.append(service_name)
error_details.append({
"service": service_name,
"error": service_data.get("error", "Unknown error"),
"response_status": service_data.get("response_status"),
"response_text": service_data.get("response_text", ""),
"duration_ms": service_data.get("duration_ms", 0)
})
# Check Redis for additional error information
client = await redis.get_client()
error_key = f"session:{session_id}:errors"
redis_errors = await client.get(error_key)
if redis_errors:
import json
try:
additional_errors = json.loads(redis_errors)
if isinstance(additional_errors, list):
error_details.extend(additional_errors)
elif isinstance(additional_errors, dict):
error_details.append(additional_errors)
except json.JSONDecodeError:
logger.warning("Failed to parse Redis error data", session_id=session_id)
# Create comprehensive error report
error_report = {
"session_id": session_id,
"status": session.status.value,
"has_errors": True,
"failed_services": failed_services,
"error_count": len(error_details),
"errors": error_details,
"cloning_started_at": session.cloning_started_at.isoformat() if session.cloning_started_at else None,
"cloning_completed_at": session.cloning_completed_at.isoformat() if session.cloning_completed_at else None,
"total_records_cloned": session.total_records_cloned,
"demo_account_type": session.demo_account_type
}
# Add troubleshooting suggestions
suggestions = []
if "tenant" in failed_services:
suggestions.append("Check if tenant service is running and accessible")
suggestions.append("Verify base tenant ID configuration")
if "auth" in failed_services:
suggestions.append("Check if auth service is running and accessible")
suggestions.append("Verify seed data files for auth service")
if any(svc in failed_services for svc in ["inventory", "recipes", "suppliers", "production"]):
suggestions.append("Check if the specific service is running and accessible")
suggestions.append("Verify seed data files exist and are valid")
if any("timeout" in error.get("error", "").lower() for error in error_details):
suggestions.append("Check service response times and consider increasing timeouts")
suggestions.append("Verify network connectivity between services")
if any("network" in error.get("error", "").lower() for error in error_details):
suggestions.append("Check network connectivity between demo-session and other services")
suggestions.append("Verify DNS resolution and service discovery")
if suggestions:
error_report["troubleshooting_suggestions"] = suggestions
return error_report
except Exception as e:
logger.error(
"Failed to retrieve session errors",
session_id=session_id,
error=str(e),
exc_info=True
)
raise HTTPException(
status_code=500,
detail=f"Failed to retrieve error details: {str(e)}"
)
@router.post(
route_builder.build_resource_detail_route("sessions", "session_id", include_tenant_prefix=False) + "/retry",
response_model=dict