refactor: rename thumbnail_rendering queue to asset_pipeline
The queue handles far more than thumbnails: OCC tessellation, USD master generation, GLB production, order line renders, and workflow renders. asset_pipeline better reflects its role as the render-worker's primary queue. Updated all references in: task decorators, celery_app.py, beat_tasks.py, docker-compose.yml worker command, worker.py MONITORED_QUEUES, admin.py, CLAUDE.md, LEARNINGS.md, Dockerfile, helpTexts.ts, test files, and all .claude/commands/*.md skill files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -366,7 +366,7 @@ async def update_settings(
|
||||
await db.commit()
|
||||
|
||||
# Note: blender-renderer HTTP service removed; concurrency is now controlled
|
||||
# via render-worker Docker concurrency setting (thumbnail_rendering queue).
|
||||
# via render-worker Docker concurrency setting (asset_pipeline queue).
|
||||
|
||||
return _settings_to_out(await _load_settings(db))
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""CAD file router - serve thumbnails, glTF models, parsed objects, and trigger reprocessing."""
|
||||
import logging
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
@@ -20,6 +21,7 @@ from app.utils.auth import get_current_user, is_privileged
|
||||
from app.services.product_service import link_cad_to_product, lookup_product
|
||||
|
||||
router = APIRouter(prefix="/cad", tags=["cad"])
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -273,6 +275,7 @@ async def get_objects(
|
||||
"cad_file_id": str(cad.id),
|
||||
"original_name": cad.original_name,
|
||||
"processing_status": cad.processing_status.value,
|
||||
"step_hash": cad.step_file_hash,
|
||||
"parsed_objects": cad.parsed_objects,
|
||||
}
|
||||
|
||||
@@ -318,6 +321,11 @@ async def generate_gltf_production(
|
||||
if not cad.stored_path:
|
||||
raise HTTPException(status_code=404, detail="STEP file not uploaded for this CAD file")
|
||||
|
||||
logger.warning(
|
||||
"generate_gltf_production called for cad %s — "
|
||||
"deprecated: renders now consume usd_master directly",
|
||||
id,
|
||||
)
|
||||
from app.tasks.step_tasks import generate_gltf_production_task
|
||||
task = generate_gltf_production_task.delay(str(id))
|
||||
return {"status": "queued", "task_id": task.id, "cad_file_id": str(id)}
|
||||
|
||||
@@ -1000,6 +1000,53 @@ async def cancel_line_render(
|
||||
}
|
||||
|
||||
|
||||
class RejectLineBody(BaseModel):
|
||||
reason: str = ""
|
||||
|
||||
|
||||
@router.post("/{order_id}/lines/{line_id}/reject", status_code=200)
|
||||
async def reject_order_line(
|
||||
order_id: uuid.UUID,
|
||||
line_id: uuid.UUID,
|
||||
body: RejectLineBody,
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Reject a single order line (admin/PM only).
|
||||
|
||||
Sets item_status to 'rejected' and stores the reason in the notes field.
|
||||
"""
|
||||
if not _is_privileged(user):
|
||||
raise HTTPException(status_code=403, detail="Insufficient permissions")
|
||||
|
||||
result = await db.execute(select(Order).where(Order.id == order_id))
|
||||
order = result.scalar_one_or_none()
|
||||
if not order:
|
||||
raise HTTPException(404, detail="Order not found")
|
||||
|
||||
line_result = await db.execute(
|
||||
select(OrderLine).where(OrderLine.id == line_id, OrderLine.order_id == order_id)
|
||||
)
|
||||
line = line_result.scalar_one_or_none()
|
||||
if not line:
|
||||
raise HTTPException(404, detail="Order line not found")
|
||||
|
||||
from sqlalchemy import update as sql_update
|
||||
|
||||
notes_value = body.reason.strip() if body.reason and body.reason.strip() else line.notes
|
||||
await db.execute(
|
||||
sql_update(OrderLine)
|
||||
.where(OrderLine.id == line.id)
|
||||
.values(
|
||||
item_status="rejected",
|
||||
notes=notes_value,
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
return {"rejected": True, "line_id": str(line.id), "reason": body.reason}
|
||||
|
||||
|
||||
@router.post("/{order_id}/cancel-renders")
|
||||
async def cancel_order_renders(
|
||||
order_id: uuid.UUID,
|
||||
|
||||
@@ -237,7 +237,7 @@ async def reprocess_cad_file(
|
||||
# Queue inspection + control
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
MONITORED_QUEUES = ["step_processing", "thumbnail_rendering", "ai_validation"]
|
||||
MONITORED_QUEUES = ["step_processing", "asset_pipeline", "ai_validation"]
|
||||
|
||||
|
||||
def _parse_redis_task(raw: str) -> dict | None:
|
||||
@@ -515,7 +515,7 @@ async def render_health(
|
||||
|
||||
details: dict = {}
|
||||
|
||||
# 1. Check if render-worker (thumbnail_rendering queue) is connected + has Blender
|
||||
# 1. Check if render-worker (asset_pipeline queue) is connected + has Blender
|
||||
render_worker_connected = False
|
||||
blender_available = False
|
||||
|
||||
@@ -534,10 +534,10 @@ async def render_health(
|
||||
else:
|
||||
all_workers = list(inspect_result.get("ping", {}).keys())
|
||||
details["workers"] = all_workers
|
||||
# Find any worker consuming thumbnail_rendering queue
|
||||
# Find any worker consuming asset_pipeline queue
|
||||
for worker_name, queues in inspect_result.get("active_queues", {}).items():
|
||||
queue_names = [q.get("name") for q in (queues or [])]
|
||||
if "thumbnail_rendering" in queue_names:
|
||||
if "asset_pipeline" in queue_names:
|
||||
render_worker_connected = True
|
||||
# render-worker always has Blender — it starts Blender successfully
|
||||
blender_available = True
|
||||
@@ -547,11 +547,11 @@ async def render_health(
|
||||
render_worker_connected = True
|
||||
details["worker_detection"] = "fallback"
|
||||
|
||||
# 3. Queue depth for thumbnail_rendering
|
||||
# 3. Queue depth for asset_pipeline
|
||||
thumbnail_queue_depth = 0
|
||||
try:
|
||||
r = redis_lib.from_url(app_settings.redis_url, decode_responses=True)
|
||||
thumbnail_queue_depth = r.llen("thumbnail_rendering") or 0
|
||||
thumbnail_queue_depth = r.llen("asset_pipeline") or 0
|
||||
except Exception as exc:
|
||||
details["redis_error"] = str(exc)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user