feat: multi-GPU queue routing for legacy still renders (M2)

dispatch_order_line_render now routes still renders (non-animation,
non-cinematic) to a secondary GPU queue when MULTI_GPU_LIGHT_RENDER_QUEUE
is configured and that queue has active Celery workers.

- config.py: multi_gpu_light_render_queue setting (default "" = disabled)
- render_order_line.py: implement the routing stub — load output_type via
  selectinload, check render_settings.animation + .cinematic flags, call
  _inspect_active_worker_queues (reused from workflow_graph_runtime) with
  0.5s timeout to check if the light queue is live

No behaviour change when MULTI_GPU_LIGHT_RENDER_QUEUE is not set.
Enable by setting it to "asset_pipeline_light" and adding a
render-worker-light service with concurrency=1 to docker-compose.

docs: learnings erfasst — multi-GPU queue routing M2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 15:12:07 +02:00
co-authored by Claude Sonnet 4.6
parent 3401b06b19
commit 23605783bd
3 changed files with 34 additions and 5 deletions
+7
View File
@@ -75,7 +75,14 @@ class Settings(BaseSettings):
# Redis / Celery
redis_url: str = "redis://localhost:6379/0"
# Queue for shadow-mode workflow renders (second GPU worker).
workflow_shadow_render_queue: str = "asset_pipeline_light"
# When non-empty AND that queue has active workers, still renders from the
# legacy dispatch path are routed here instead of asset_pipeline, enabling
# concurrent still rendering on multi-GPU setups.
# Set MULTI_GPU_LIGHT_RENDER_QUEUE=asset_pipeline_light in docker-compose
# for the render-worker-light service and restart the workers.
multi_gpu_light_render_queue: str = ""
@model_validator(mode="after")
def normalize_runtime_hosts(self) -> "Settings":
@@ -42,13 +42,32 @@ def dispatch_order_line_render(order_line_id: str):
logger.info(f"OrderLine {order_line_id}: order {order.status.value} — not dispatching")
return
# All renders go to asset_pipeline (single-GPU default).
# For multi-GPU setups: enable render-worker-light in docker-compose
# and change target_queue logic below to route small stills to
# asset_pipeline_light for concurrent rendering.
pass
# Multi-GPU routing: route still renders to a secondary GPU queue when
# MULTI_GPU_LIGHT_RENDER_QUEUE is configured and that queue is active.
is_still_render = False
if line:
from sqlalchemy.orm import selectinload
line_full = session.execute(
select(OrderLine)
.options(selectinload(OrderLine.output_type))
.where(OrderLine.id == order_line_id)
).scalar_one_or_none()
if line_full and line_full.output_type:
rs = line_full.output_type.render_settings or {}
is_still_render = not rs.get("animation") and not rs.get("cinematic")
light_queue = app_settings.multi_gpu_light_render_queue.strip()
target_queue = "asset_pipeline"
if light_queue and is_still_render:
from app.domains.rendering.workflow_graph_runtime import _inspect_active_worker_queues
active_queues = _inspect_active_worker_queues(timeout=0.5)
if light_queue in active_queues:
target_queue = light_queue
logger.info(
"Multi-GPU routing: order_line %s (still) -> queue=%s",
order_line_id,
target_queue,
)
logger.info(f"Dispatching render for order line: {order_line_id} -> queue={target_queue}")
render_order_line_task.apply_async(args=[order_line_id], queue=target_queue)