feat(refactor/phase2): pipeline modularity + dead code removal

Phase 2.3 — Fix render cancellation (real Celery task ID):
  - orders.py cancel endpoints: read celery_task_id from render_job_doc
    instead of synthetic "render-{line_id}" which was a no-op
  - render_order_line_still_task: creates RenderJobDocument at task start,
    stores self.request.id as celery_task_id, writes step-level state
    (RESOLVE_STEP_PATH → BLENDER_STILL) back to order_lines.render_job_doc

Phase 3.1 — Remove Pillow overlay dead code:
  - blender_render.py: deleted 55-line Pillow post-processing block
    (lines 798-851, green bar + model name label)
  - transparent_bg=True is always passed; the else branch was unreachable
  - Removed mention from script docstring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 19:27:33 +01:00
parent ea31ed657c
commit 966c3aed57
4 changed files with 200 additions and 64 deletions
+48
View File
@@ -395,14 +395,47 @@ def render_order_line_still_task(self, order_line_id: str, **params) -> dict:
Wraps render_still_task logic but accepts order_line_id instead of step_path.
On success, creates a MediaAsset record via publish_asset.
"""
import asyncio
from app.domains.rendering.job_document import RenderJobDocument, JobState
from app.core.process_steps import StepName
log_task_event(self.request.id, f"Starting render_order_line_still_task: order_line={order_line_id}", "info")
# Initialise job document and store real Celery task ID
job_doc = RenderJobDocument.new(order_line_id=order_line_id, celery_task_id=self.request.id)
job_doc.set_state(JobState.RUNNING)
def _save_job_doc():
async def _run():
from app.database import AsyncSessionLocal
from app.domains.orders.models import OrderLine
from sqlalchemy import update as _upd
async with AsyncSessionLocal() as db:
await db.execute(
_upd(OrderLine)
.where(OrderLine.id == order_line_id)
.values(render_job_doc=job_doc.to_dict())
)
await db.commit()
try:
asyncio.get_event_loop().run_until_complete(_run())
except Exception as _exc:
logger.debug("_save_job_doc failed: %s", _exc)
_save_job_doc()
job_doc.begin_step(StepName.RESOLVE_STEP_PATH)
step_path_str, cad_file_id = _resolve_step_path_for_order_line(order_line_id)
if not step_path_str:
job_doc.fail_step(StepName.RESOLVE_STEP_PATH, "product missing or has no linked CAD file")
job_doc.set_state(JobState.FAILED, error="Cannot resolve STEP path")
_save_job_doc()
log_task_event(self.request.id, f"Failed: cannot resolve STEP path for order_line {order_line_id}", "error")
raise RuntimeError(
f"Cannot resolve STEP path for order_line {order_line_id}: "
"product missing or has no linked CAD file"
)
job_doc.finish_step(StepName.RESOLVE_STEP_PATH, output={"step_path": step_path_str})
step = Path(step_path_str)
output_dir = step.parent / "renders"
@@ -410,12 +443,24 @@ def render_order_line_still_task(self, order_line_id: str, **params) -> dict:
output_path = output_dir / f"line_{order_line_id}.png"
try:
job_doc.begin_step(StepName.BLENDER_STILL)
from app.services.render_blender import render_still
result = render_still(
step_path=step,
output_path=output_path,
**params,
)
job_doc.finish_step(
StepName.BLENDER_STILL,
output={"output_path": str(output_path), "duration_s": result.get("total_duration_s")},
)
job_doc.set_state(JobState.COMPLETED, result={
"output_path": str(output_path),
"duration_s": result.get("total_duration_s"),
"engine_used": result.get("engine_used"),
})
_save_job_doc()
publish_asset.delay(
order_line_id,
"still",
@@ -438,6 +483,9 @@ def render_order_line_still_task(self, order_line_id: str, **params) -> dict:
_update_workflow_run_status(order_line_id, "completed")
return result
except Exception as exc:
job_doc.fail_step(StepName.BLENDER_STILL, str(exc))
job_doc.set_state(JobState.FAILED, error=str(exc))
_save_job_doc()
log_task_event(self.request.id, f"Failed: {exc}", "error")
logger.error("render_order_line_still_task failed for %s: %s", order_line_id, exc)
try: