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:
2026-03-12 22:28:38 +01:00
parent e7b70a35ea
commit 1321ef2bd4
39 changed files with 540 additions and 122 deletions
+1 -1
View File
@@ -84,4 +84,4 @@ COPY backend/ .
# Verify Blender version at build time if binary is available
# (skipped during build since /opt/blender is a host mount)
CMD ["bash", "-c", "python3 /check_version.py && celery -A app.tasks.celery_app worker --loglevel=info -Q thumbnail_rendering --concurrency=1"]
CMD ["bash", "-c", "python3 /check_version.py && celery -A app.tasks.celery_app worker --loglevel=info -Q asset_pipeline --concurrency=1"]
+37 -2
View File
@@ -488,13 +488,19 @@ def _collect_part_key_map(shape_tool, free_labels) -> dict:
return part_key_map
def _inject_glb_extras(glb_path: Path, extras: dict) -> None:
def _inject_glb_extras(glb_path: Path, extras: dict, part_key_map: dict | None = None) -> None:
"""Patch a GLB binary to add/update scenes[0].extras JSON field.
Also stamps per-node extras.partKey on each GLB node whose name maps to an
entry in part_key_map (the dict returned by _collect_part_key_map). Three.js
GLTFLoader propagates node extras → object.userData, so every THREE.Mesh will
carry userData.partKey after load — no runtime lookup needed in the viewer.
The GLB format stores a JSON chunk immediately after the 12-byte header.
We re-serialize it with the new extras and update chunk + total lengths.
No external dependencies — pure stdlib struct/json.
"""
import re as _re
import struct as _struct
data = glb_path.read_bytes()
@@ -515,6 +521,35 @@ def _inject_glb_extras(glb_path: Path, extras: dict) -> None:
else:
j.setdefault("extras", {}).update(extras)
# Stamp per-node extras.partKey so Three.js maps it to mesh.userData.partKey.
# part_key_map keys are raw OCC names with _AF\d+ stripped but not slugified
# (e.g. "GE360-HF_000_P_ASM_1" → "ge360_hf_000_p_asm_1").
# GLB node names are raw OCC names (may or may not have _AF\d+ suffix).
# Normalize both sides to slugified form for the lookup.
if part_key_map:
_norm_re = _re.compile(r'_AF\d+$', _re.IGNORECASE)
def _slugify(s: str) -> str:
return _re.sub(r'[^a-z0-9]+', '_', _norm_re.sub('', s).lower()).strip('_')
# Build a slug→partKey lookup from the part_key_map
# part_key_map: {raw_name_no_af_suffix: part_key_slug}
slug_to_part_key: dict = {}
for raw_key, part_key in part_key_map.items():
slug_to_part_key[_slugify(raw_key)] = part_key
n_stamped = 0
for node in j.get("nodes", []):
raw = node.get("name", "")
if not raw:
continue
slug = _slugify(raw)
part_key = slug_to_part_key.get(slug)
if part_key:
node.setdefault("extras", {})["partKey"] = part_key
n_stamped += 1
print(f"Stamped partKey extras on {n_stamped} GLB nodes")
new_json = json.dumps(j, separators=(",", ":"))
# Pad to 4-byte boundary with spaces (required by GLB spec)
pad = (4 - len(new_json) % 4) % 4
@@ -720,7 +755,7 @@ def main() -> None:
if part_key_map:
extras_payload["partKeyMap"] = part_key_map
if extras_payload:
_inject_glb_extras(out, extras_payload)
_inject_glb_extras(out, extras_payload, part_key_map=part_key_map if part_key_map else None)
if sharp_pairs:
print(f"Injected {len(sharp_pairs)} sharp edge segment pairs into GLB extras")
if part_key_map:
+4 -1
View File
@@ -616,7 +616,10 @@ def main() -> None:
continue
part_path = f"{node_path}/{part_key}"
mesh_path = f"{part_path}/Mesh"
# Name the Mesh prim after part_key so Blender imports it with the
# part name directly (Blender collapses single-child Xform+Mesh into
# just the Mesh object, using the mesh prim's leaf name as object name).
mesh_path = f"{part_path}/{part_key}"
# ── Xform prim ────────────────────────────────────────────────
xform = UsdGeom.Xform.Define(stage, part_path)