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:
@@ -157,7 +157,6 @@ def generate_stl_cache(self, cad_file_id: str, quality: str):
|
||||
from sqlalchemy.orm import Session
|
||||
from app.config import settings as app_settings
|
||||
from app.models.cad_file import CadFile
|
||||
import httpx
|
||||
|
||||
logger.info(f"Generating {quality}-quality STL for CAD file: {cad_file_id}")
|
||||
|
||||
@@ -172,16 +171,20 @@ def generate_stl_cache(self, cad_file_id: str, quality: str):
|
||||
eng.dispose()
|
||||
|
||||
try:
|
||||
resp = httpx.post(
|
||||
"http://blender-renderer:8100/convert-stl",
|
||||
json={"step_path": step_path, "quality": quality},
|
||||
timeout=600.0,
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
logger.info(f"STL cached: {data['stl_path']} ({data['size_bytes']} bytes) in {data['duration_s']}s")
|
||||
else:
|
||||
raise RuntimeError(f"blender-renderer returned {resp.status_code}: {resp.text[:300]}")
|
||||
from app.services.render_blender import convert_step_to_stl, export_per_part_stls
|
||||
from pathlib import Path as _Path
|
||||
step = _Path(step_path)
|
||||
stl_out = step.parent / f"{step.stem}_{quality}.stl"
|
||||
parts_dir = step.parent / f"{step.stem}_{quality}_parts"
|
||||
|
||||
if not stl_out.exists() or stl_out.stat().st_size == 0:
|
||||
convert_step_to_stl(step, stl_out, quality)
|
||||
if not (parts_dir / "manifest.json").exists():
|
||||
try:
|
||||
export_per_part_stls(step, parts_dir, quality)
|
||||
except Exception as pe:
|
||||
logger.warning(f"Per-part STL export non-fatal: {pe}")
|
||||
logger.info(f"STL cached: {stl_out} ({stl_out.stat().st_size // 1024} KB)")
|
||||
except Exception as exc:
|
||||
logger.error(f"STL generation failed for {cad_file_id} quality={quality}: {exc}")
|
||||
raise self.retry(exc=exc, countdown=30, max_retries=2)
|
||||
|
||||
Reference in New Issue
Block a user