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:
@@ -105,6 +105,10 @@ def build_scene_manifest(cad_file, usd_asset=None) -> dict:
|
||||
object_names: list[str] = cad_file.parsed_objects.get("objects") or []
|
||||
seen_keys: set[str] = set()
|
||||
for source_name in object_names:
|
||||
# Fallback: USD master not yet generated. Use source_name as xcaf_path proxy.
|
||||
# Note: slugs produced here may differ from what export_step_to_usd.py will
|
||||
# produce for unnamed parts (which use sha256 of the XCAF hierarchy path).
|
||||
# Named parts will match once USD master is generated.
|
||||
part_key = generate_part_key(source_name, source_name, seen_keys)
|
||||
effective_material, provenance = _resolve_material(
|
||||
part_key, source_name, manual, resolved, source
|
||||
|
||||
@@ -15,8 +15,8 @@ from pathlib import Path
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _glb_from_step(step_path: Path, glb_path: Path) -> None:
|
||||
"""Convert STEP → GLB via OCC (export_step_to_gltf.py, no Blender needed)."""
|
||||
def _glb_from_step(step_path: Path, glb_path: Path, tessellation_engine: str = "occ") -> None:
|
||||
"""Convert STEP → GLB via OCC or GMSH (export_step_to_gltf.py, no Blender needed)."""
|
||||
import subprocess
|
||||
import sys as _sys
|
||||
|
||||
@@ -32,12 +32,13 @@ def _glb_from_step(step_path: Path, glb_path: Path) -> None:
|
||||
"--output_path", str(glb_path),
|
||||
"--linear_deflection", str(linear_deflection),
|
||||
"--angular_deflection", str(angular_deflection),
|
||||
"--tessellation_engine", tessellation_engine,
|
||||
]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
||||
for line in result.stdout.splitlines():
|
||||
logger.info("[occ-gltf] %s", line)
|
||||
logger.info("[export-gltf] %s", line)
|
||||
for line in result.stderr.splitlines():
|
||||
logger.warning("[occ-gltf stderr] %s", line)
|
||||
logger.warning("[export-gltf stderr] %s", line)
|
||||
if result.returncode != 0 or not glb_path.exists() or glb_path.stat().st_size == 0:
|
||||
raise RuntimeError(
|
||||
f"export_step_to_gltf.py failed (exit {result.returncode}).\n"
|
||||
@@ -90,8 +91,9 @@ def render_still(
|
||||
mesh_attributes: dict | None = None,
|
||||
log_callback: "Callable[[str], None] | None" = None,
|
||||
usd_path: "Path | None" = None,
|
||||
tessellation_engine: str = "occ",
|
||||
) -> dict:
|
||||
"""Convert STEP → GLB (OCC) → PNG (Blender subprocess).
|
||||
"""Convert STEP → GLB (OCC or GMSH) → PNG (Blender subprocess).
|
||||
|
||||
When usd_path is provided and the file exists, the GLB conversion step is
|
||||
skipped and Blender imports the USD stage directly (--usd-path flag).
|
||||
@@ -125,7 +127,7 @@ def render_still(
|
||||
glb_size_bytes = 0
|
||||
else:
|
||||
if not glb_path.exists() or glb_path.stat().st_size == 0:
|
||||
_glb_from_step(step_path, glb_path)
|
||||
_glb_from_step(step_path, glb_path, tessellation_engine)
|
||||
else:
|
||||
logger.info("GLB local hit: %s (%d KB)", glb_path.name, glb_path.stat().st_size // 1024)
|
||||
glb_size_bytes = glb_path.stat().st_size if glb_path.exists() else 0
|
||||
@@ -310,6 +312,7 @@ def render_turntable_to_file(
|
||||
rotation_y: float = 0.0,
|
||||
rotation_z: float = 0.0,
|
||||
usd_path: "Path | None" = None,
|
||||
tessellation_engine: str = "occ",
|
||||
) -> dict:
|
||||
"""Render a turntable animation: STEP → STL → N frames (Blender) → mp4 (ffmpeg).
|
||||
|
||||
@@ -349,7 +352,7 @@ def render_turntable_to_file(
|
||||
logger.info("[render_blender] turntable using USD path: %s", usd_path)
|
||||
else:
|
||||
if not glb_path.exists() or glb_path.stat().st_size == 0:
|
||||
_glb_from_step(step_path, glb_path)
|
||||
_glb_from_step(step_path, glb_path, tessellation_engine)
|
||||
else:
|
||||
logger.info("GLB local hit: %s (%d KB)", glb_path.name, glb_path.stat().st_size // 1024)
|
||||
glb_duration_s = round(time.monotonic() - t_glb, 2)
|
||||
|
||||
@@ -79,7 +79,7 @@ def match_cad_to_items(
|
||||
return matched
|
||||
|
||||
|
||||
def extract_cad_metadata(cad_file_id: str) -> None:
|
||||
def extract_cad_metadata(cad_file_id: str, tenant_id: str | None = None) -> None:
|
||||
"""
|
||||
Fast metadata extraction for a CAD file (no thumbnail generation).
|
||||
|
||||
@@ -94,9 +94,11 @@ def extract_cad_metadata(cad_file_id: str) -> None:
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import Session
|
||||
from app.models.cad_file import CadFile, ProcessingStatus
|
||||
from app.core.tenant_context import set_tenant_context_sync
|
||||
|
||||
engine = create_engine(settings.database_url_sync)
|
||||
with Session(engine) as session:
|
||||
set_tenant_context_sync(session, tenant_id)
|
||||
cad_file = session.get(CadFile, uuid.UUID(cad_file_id))
|
||||
if not cad_file:
|
||||
logger.error(f"CAD file not found: {cad_file_id}")
|
||||
@@ -452,6 +454,7 @@ def _get_all_settings() -> dict[str, str]:
|
||||
"thumbnail_format": "jpg",
|
||||
"blender_smooth_angle": "30",
|
||||
"cycles_device": "auto",
|
||||
"tessellation_engine": "occ",
|
||||
}
|
||||
try:
|
||||
from app.config import settings as app_settings
|
||||
@@ -533,6 +536,7 @@ def _generate_thumbnail(
|
||||
samples=samples,
|
||||
smooth_angle=int(settings["blender_smooth_angle"]),
|
||||
cycles_device=settings["cycles_device"],
|
||||
tessellation_engine=settings["tessellation_engine"],
|
||||
)
|
||||
rendered_png = tmp_png if tmp_png.exists() else None
|
||||
except Exception as exc:
|
||||
@@ -642,6 +646,7 @@ def render_to_file(
|
||||
denoising_use_gpu: str = "",
|
||||
order_line_id: str | None = None,
|
||||
usd_path: "Path | None" = None,
|
||||
tessellation_engine: str | None = None,
|
||||
) -> tuple[bool, dict]:
|
||||
"""Render a STEP file to a specific output path using current system settings.
|
||||
|
||||
@@ -777,6 +782,7 @@ def render_to_file(
|
||||
denoising_use_gpu=denoising_use_gpu,
|
||||
log_callback=_log_cb,
|
||||
usd_path=usd_path,
|
||||
tessellation_engine=tessellation_engine or settings["tessellation_engine"],
|
||||
)
|
||||
rendered_png = tmp_png if tmp_png.exists() else None
|
||||
except Exception as exc:
|
||||
|
||||
Reference in New Issue
Block a user