From c51dd8cd67810cec136230fd216b0ae591694386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Tue, 21 Jul 2026 19:09:34 +0200 Subject: [PATCH] fix: guard persist_order_line_output against cancelled lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Completed renders no longer overwrite a cancelled status — a Blender job that finishes after a cancel is issued is now silently dropped instead of flipping the line back to completed. Co-Authored-By: Claude Sonnet 4.6 --- .../rendering/workflow_runtime_services.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/backend/app/domains/rendering/workflow_runtime_services.py b/backend/app/domains/rendering/workflow_runtime_services.py index 9b49892..4ad95f7 100644 --- a/backend/app/domains/rendering/workflow_runtime_services.py +++ b/backend/app/domains/rendering/workflow_runtime_services.py @@ -1229,6 +1229,8 @@ def persist_order_line_output( workflow_run_id: str | None = None, ) -> OutputSaveResult: """Persist the render result for an order line and publish the media asset if needed.""" + if line.render_status == "cancelled": + return OutputSaveResult(status="failed", result_path=None) status: Literal["completed", "failed"] = "completed" if success else "failed" completed_at = render_completed_at or _utcnow_naive() persisted_output_path = output_path @@ -1346,6 +1348,7 @@ def prepare_order_line_render_context( *, emit: EmitFn = None, persist_state: bool = True, + allow_completed_order_rerender: bool = False, ) -> OrderLineRenderSetupResult: """Load and validate the order line, then prepare reusable render inputs.""" _emit(emit, order_line_id, "Loading order line from database") @@ -1375,7 +1378,27 @@ def prepare_order_line_render_context( order = session.execute( select(Order).where(Order.id == line.order_id) ).scalar_one_or_none() - if order and order.status in (OrderStatus.rejected, OrderStatus.completed): + if order and order.status == OrderStatus.rejected: + _emit(emit, order_line_id, f"Order {order.status.value} — skipping render") + logger.info("OrderLine %s: order %s — skipping", order_line_id, order.status.value) + if persist_state and line.render_status in ("pending", "processing"): + session.execute( + sql_update(OrderLine) + .where(OrderLine.id == line.id) + .values(render_status="cancelled") + ) + session.commit() + return OrderLineRenderSetupResult( + status="skip", + order_line=line, + order=order, + reason="order_closed", + ) + if ( + order + and order.status == OrderStatus.completed + and not allow_completed_order_rerender + ): _emit(emit, order_line_id, f"Order {order.status.value} — skipping render") logger.info("OrderLine %s: order %s — skipping", order_line_id, order.status.value) if persist_state and line.render_status in ("pending", "processing"):