Files
xiaoxia-saas/packages/application/generation_tasks.py
T
xiaoxia c873bb635f
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 55s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m13s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 2m46s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m51s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 3m6s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m59s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m14s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m53s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m6s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m6s
CI/CD Pipeline / Build Staging API Image (push) Successful in 7m12s
AI Code Review / AI Code Review (pull_request) Failing after 6m19s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 39s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 8m57s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m2s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m55s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m9s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m16s
CI/CD Pipeline / Integration Tests (push) Successful in 3m12s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m13s
CI/CD Pipeline / Unit Tests (push) Successful in 14m24s
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Successful in 12m30s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 8s
refactor: 统一渲染链路,预览即所得(-3370行) (#1479)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-08-24 14:16:00 +08:00

143 lines
4.8 KiB
Python
Executable File

from __future__ import annotations
from dataclasses import dataclass, field
from uuid import uuid4
from packages.domain import GenerationTask
from packages.ports.generation_task_repository import GenerationTaskRepository
@dataclass(slots=True)
class CreateGenerationTaskCommand:
project_id: str = ""
asset_library_id: str = ""
strategy_id: str = ""
voice_library_id: str = ""
template_id: str = ""
asset_ids: list[str] = field(default_factory=list)
title_ids: list[str] = field(default_factory=list)
voice_ids: list[str] = field(default_factory=list)
created_by_user_id: str = ""
source_edit_plan_id: str = ""
asset_select_mode: str = ""
batch_id: str = ""
video_title: str = ""
resolution: str = ""
bgm_config: dict = field(default_factory=dict)
auto_retry_enabled: bool = False
auto_retry_max: int = 0
is_preview: bool = False
source_task_id: str = ""
output_width: int = 1280
output_height: int = 720
cover_url: str = ""
title_config: dict = field(default_factory=dict)
class CreateGenerationTaskUseCase:
def __init__(self, generation_task_repository: GenerationTaskRepository):
self.generation_task_repository = generation_task_repository
def execute(self, command: CreateGenerationTaskCommand) -> GenerationTask:
task = GenerationTask(
id=uuid4().hex,
project_id=command.project_id,
asset_library_id=command.asset_library_id,
strategy_id=command.strategy_id,
voice_library_id=command.voice_library_id,
template_id=command.template_id,
asset_ids=command.asset_ids,
title_ids=command.title_ids,
voice_ids=command.voice_ids,
status="pending", # type: ignore[arg-type]
progress=0.0,
result_count=0,
error_message="",
created_by_user_id=command.created_by_user_id,
source_edit_plan_id=command.source_edit_plan_id,
asset_select_mode=command.asset_select_mode,
batch_id=command.batch_id,
video_title=command.video_title,
resolution=command.resolution,
bgm_config=command.bgm_config,
auto_retry_enabled=command.auto_retry_enabled,
auto_retry_max=command.auto_retry_max,
is_preview=command.is_preview,
source_task_id=command.source_task_id,
output_width=command.output_width,
output_height=command.output_height,
cover_url=command.cover_url,
title_config=command.title_config,
)
return self.generation_task_repository.create(task)
class GetGenerationTaskUseCase:
def __init__(self, generation_task_repository: GenerationTaskRepository):
self.generation_task_repository = generation_task_repository
def execute(self, task_id: str) -> GenerationTask | None:
return self.generation_task_repository.get(task_id)
@dataclass(slots=True)
class ListTasksFilter:
"""任务列表筛选条件。"""
status: str | None = None # pending, running, completed, failed, cancelled
@dataclass(slots=True)
class ListGenerationTasksResult:
"""带筛选和分页的任务列表结果。"""
items: list[GenerationTask]
total: int
class ListUserTasksFilteredUseCase:
"""按用户+筛选条件查询任务列表。"""
def __init__(self, generation_task_repository: GenerationTaskRepository):
self.generation_task_repository = generation_task_repository
def execute(
self,
user_id: str,
*,
status: str | None = None,
limit: int | None = None,
offset: int = 0,
) -> ListGenerationTasksResult:
items = self.generation_task_repository.list_by_user_filtered(
user_id,
status=status,
limit=limit,
offset=offset,
)
total = self.generation_task_repository.count_by_user_filtered(
user_id,
status=status,
)
return ListGenerationTasksResult(items=items, total=total)
class RetryGenerationTaskUseCase:
"""原地重试失败的任务(重置状态+递增retry_count)。
与创建新任务不同:复用同一个 task_id,保留历史关联。
"""
def __init__(self, generation_task_repository: GenerationTaskRepository):
self.generation_task_repository = generation_task_repository
def execute(self, task_id: str) -> GenerationTask:
task = self.generation_task_repository.get(task_id)
if task is None:
raise ValueError(f"任务不存在: {task_id}")
if not task.is_failed:
raise ValueError(f"只有失败状态的任务才能重试,当前状态: {task.status.value}")
task.mark_pending_from_failed()
self.generation_task_repository.update(task)
return task