refactor(A2): replace blender-renderer HTTP service with render-worker Celery container

- Create render-worker/ with Dockerfile (Ubuntu + cadquery + Blender via host mount)
- Add render-worker/check_version.py: verifies Blender >= 5.0.1 at startup, Exit 1 on failure
- Add render-worker/scripts/: blender_render.py, still_render.py, turntable_render.py
- Create backend/app/services/render_blender.py: direct subprocess rendering
  - convert_step_to_stl() and export_per_part_stls() using cadquery
  - render_still(): STEP → STL → PNG via Blender subprocess
  - is_blender_available(): detects BLENDER_BIN env for render-worker context
- Create backend/app/domains/rendering/tasks.py: render_still_task + render_turntable_task
- Update step_processor.py: use subprocess path when BLENDER_BIN env is set (render-worker)
- Update step_tasks.py: generate_stl_cache uses direct cadquery instead of HTTP
- Remove blender-renderer and threejs-renderer from docker-compose.yml
- Replace worker-thumbnail with render-worker (Ubuntu + cadquery + Blender mount)
- Remove Docker SDK from backend Dockerfile (was only for flamenco scaling)
- Update .env.example: BLENDER_VERSION=5.0.1 documented
- Update celery_app.py: include domains.rendering.tasks in autodiscover

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 15:48:46 +01:00
parent 1d6864fb64
commit 9d1a820295
16 changed files with 3118 additions and 108 deletions
+68
View File
@@ -0,0 +1,68 @@
"""Startup check: verify Blender >= 5.0.1 is available.
Run before starting the Celery worker. Exits with code 1 if Blender is
missing or below the minimum required version.
"""
import os
import re
import subprocess
import sys
from pathlib import Path
MIN_VERSION = (5, 0, 1)
MIN_VERSION_STR = ".".join(str(v) for v in MIN_VERSION)
def find_blender() -> str:
import shutil
env_bin = os.environ.get("BLENDER_BIN", "")
if env_bin and Path(env_bin).exists():
return env_bin
found = shutil.which("blender")
return found or "blender"
def check_version():
blender_bin = find_blender()
if not Path(blender_bin).exists():
print(f"ERROR: Blender not found at {blender_bin}", file=sys.stderr)
print(
"Mount Blender >= 5.0.1 from the host via:\n"
" volumes:\n"
" - /opt/blender:/opt/blender:ro",
file=sys.stderr,
)
sys.exit(1)
try:
result = subprocess.run(
[blender_bin, "--version"],
capture_output=True, text=True, timeout=15
)
output = result.stdout or result.stderr or ""
except Exception as exc:
print(f"ERROR: Could not run Blender: {exc}", file=sys.stderr)
sys.exit(1)
match = re.search(r"Blender\s+(\d+)\.(\d+)\.(\d+)", output)
if not match:
print(f"ERROR: Could not parse Blender version from output:\n{output[:200]}", file=sys.stderr)
sys.exit(1)
version = tuple(int(x) for x in match.groups())
version_str = ".".join(str(v) for v in version)
if version < MIN_VERSION:
print(
f"ERROR: Blender {version_str} < required {MIN_VERSION_STR}.\n"
f"Update your host Blender installation.",
file=sys.stderr,
)
sys.exit(1)
print(f"Blender {version_str} OK (>= {MIN_VERSION_STR})")
if __name__ == "__main__":
check_version()