7d4e1b1b2f
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 / 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
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 46s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Failing after 49s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 54s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m29s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m45s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
从 main 分支 PR #1308 手动适配到 develop 分支,保留 develop 现有功能: Schema 层: - 新增 ConfirmGenerationRequest schema - CreateGenerationTaskRequest 增加 6 个新字段(is_preview, source_task_id, output_width, output_height, cover_url, custom_title) - GenerationTaskResponse 增加对应字段 Domain 层: - GenerationTask 实体增加 source_task_id, output_width, output_height, cover_url, custom_title 字段 - create() 工厂方法增加对应参数 Application 层: - CreateGenerationTaskCommand 增加对应字段 - UseCase 执行时传递新字段 DB 层: - GenerationTaskModel 增加 5 个新列(is_preview 已存在于 develop) - 仓储 _to_domain/create/update 映射更新 API 路由: - 新增 POST /tasks/{task_id}/confirm 端点 - 使用 safe_enqueue_generation_task 适配 develop 任务入队机制 - 更新 _to_generation_task_response 和 retry 端点 Worker 层: - _load_task_info 返回新字段 - generate_video 支持动态分辨率(output_width/output_height 覆盖默认分辨率) Alembic 迁移 054: - generation_tasks 表增加 source_task_id, output_width, output_height, cover_url, custom_title 列 单元测试: - tests/unit/test_confirm_generation.py(7 个测试用例全部通过) - 适配 develop 的 safe_enqueue_generation_task 入队机制
143 lines
4.8 KiB
Python
Executable File
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 = ""
|
|
custom_title: str = ""
|
|
|
|
|
|
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,
|
|
custom_title=command.custom_title,
|
|
)
|
|
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
|