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>
- Add per-file Redis SET NX EX 1800 locks to generate_gltf_geometry_task
and generate_usd_master_task — concurrent duplicates (e.g. double-click
of bulk action buttons) now log a warning and return immediately instead
of running two expensive OCC tessellation subprocesses on the same file
- Fix eng.dispose() called inside with Session() block in cache-hit path
of both tasks — moved to after the with block exits (Tasks 3+4 from plan)
- Add cad.updated_at = datetime.utcnow() in save_manual_material_overrides
(was missing vs parallel save_part_materials endpoint)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fine production settings (0.03mm/0.05rad) with GMSH → CharacteristicLengthMax
0.45mm → OOM kill on large assemblies even with per-solid iteration.
GMSH quality is algorithmic (conforming seams, no fan triangles) — a denser
mesh provides no extra UV-unwrap benefit. Cap GMSH tessellation at preview
settings (0.1mm/0.1rad) in the production fallback path.
Normal path (GMSH + valid geometry GLB) is unaffected — continues to reuse
_geometry.glb directly without re-tessellating.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Per-solid iteration prevents OOM on multi-part assemblies (25-part bearing:
2.3GB RAM when processing compound → ~100MB per solid with per-solid approach)
- Fix CharacteristicLengthMax multiplier 5× → 15× and cap MinimumCirclePoints
at 20 (prevents 63-pts/circle on angular_deflection=0.1rad → 231MB → 21MB)
- Geometry task timeout 120s → 600s for large assemblies
- Production task: reuse _geometry.glb when GMSH enabled (no re-tessellation)
and cache _production_geom.glb for OCC (mtime vs STEP check)
- Viewer now prefers production GLB when available (shows correct GMSH mesh)
- GMSH OpenMP multithreading (min(cpu_count,16)) for 4.4× speedup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces GMSH as an alternative to OCC BRepMesh for STEP→GLB tessellation.
GMSH produces conforming meshes that eliminate fan triangles at cylinder seam
edges — a structural limitation of OCC BRepMesh that cannot be fixed via
deflection parameters.
Changes:
- render-worker/Dockerfile: install gmsh>=4.15.0 + libglu1-mesa + libxft2
- export_step_to_gltf.py: --tessellation_engine occ|gmsh CLI arg +
_tessellate_with_gmsh() using BRep→GMSH→Poly_Triangulation write-back
- admin.py: tessellation_engine setting (SETTINGS_DEFAULTS, SettingsOut,
SettingsUpdate, validation)
- export_glb.py: pass tessellation_engine to export_step_to_gltf.py CLI in
both geometry and production GLB tasks
- Admin.tsx: radio button UI for OCC vs GMSH selection
Tested: 121 faces meshed, 0 BRepMesh fallback, 649K triangles on sample part.
Clean seam edges for UV unwrap — GMSH respects B-rep periodic face boundaries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When re-generating a production or geometry GLB, the old approach deleted the
existing MediaAsset record and created a new one with a new UUID. Any page that
had the old download_url (/api/media/{old-id}/download) cached would then get
a 404 when trying to download, because the asset ID no longer existed in the DB.
Fix: update the existing MediaAsset record in-place (same UUID, new storage_key)
so existing download URLs remain valid after regeneration. Create a new record
only if no existing one is found.
Applies to both generate_gltf_geometry_task and generate_gltf_production_task.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>