Implement FastAPI Temporal MVP pipeline

This commit is contained in:
Codex
2026-03-27 00:10:28 +08:00
commit cc03da8a94
52 changed files with 3619 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
"""Temporal workflow application service."""
from datetime import timedelta
from fastapi import HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from app.api.schemas.workflow import WorkflowStatusResponse, WorkflowStepRead
from app.domain.enums import ServiceMode
from app.infra.db.models.workflow_run import WorkflowRunORM
from app.infra.temporal.client import get_temporal_client
from app.infra.temporal.task_queues import IMAGE_PIPELINE_CONTROL_TASK_QUEUE
from app.workers.workflows.low_end_pipeline import LowEndPipelineWorkflow
from app.workers.workflows.mid_end_pipeline import MidEndPipelineWorkflow
from app.workers.workflows.types import PipelineWorkflowInput, ReviewSignalPayload
class WorkflowService:
"""Application service for Temporal workflow orchestration."""
@staticmethod
def workflow_type_for_mode(service_mode: ServiceMode) -> str:
"""Return the workflow class name for a service mode."""
if service_mode == ServiceMode.AUTO_BASIC:
return LowEndPipelineWorkflow.__name__
return MidEndPipelineWorkflow.__name__
async def start_workflow(self, workflow_input: PipelineWorkflowInput) -> None:
"""Start the appropriate Temporal workflow for an order."""
client = await get_temporal_client()
workflow_id = f"order-{workflow_input.order_id}"
workflow_callable = (
LowEndPipelineWorkflow.run
if workflow_input.service_mode == ServiceMode.AUTO_BASIC
else MidEndPipelineWorkflow.run
)
await client.start_workflow(
workflow_callable,
workflow_input,
id=workflow_id,
task_queue=IMAGE_PIPELINE_CONTROL_TASK_QUEUE,
run_timeout=timedelta(minutes=30),
task_timeout=timedelta(seconds=30),
)
async def signal_review(self, workflow_id: str, payload: ReviewSignalPayload) -> None:
"""Send a review signal to a running Temporal workflow."""
client = await get_temporal_client()
handle = client.get_workflow_handle(workflow_id=workflow_id)
await handle.signal("submit_review", payload)
async def get_workflow_status(self, session, order_id: int) -> WorkflowStatusResponse:
"""Return persisted workflow execution state for an order."""
result = await session.execute(
select(WorkflowRunORM)
.where(WorkflowRunORM.order_id == order_id)
.options(selectinload(WorkflowRunORM.steps))
)
workflow_run = result.scalar_one_or_none()
if workflow_run is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Workflow not found")
return WorkflowStatusResponse(
order_id=workflow_run.order_id,
workflow_id=workflow_run.workflow_id,
workflow_type=workflow_run.workflow_type,
workflow_status=workflow_run.status,
current_step=workflow_run.current_step,
steps=[WorkflowStepRead.model_validate(step) for step in workflow_run.steps],
created_at=workflow_run.created_at,
updated_at=workflow_run.updated_at,
)