celery worker poll 频次机制调整| celery beat 设置poll检测任务| 拆镜复刻切片删除API | 交易流水时区BUG
This commit is contained in:
@@ -12,6 +12,7 @@ from sqlalchemy.orm.attributes import flag_modified
|
||||
|
||||
from app.config import settings
|
||||
from app.enums.common import ModuleEventTypeEnum, ModuleProjectStatusEnum, ModulePromptTypeEnum, ModuleStepStatusEnum
|
||||
from app.enums.generation_task import ChatGenerationPipelineStage, ChatGenerationTaskStatus
|
||||
from app.enums.shot_replicate import ShotReplicateGenerationModeEnum, ShotReplicateStepCodeEnum, ModuleCodeEnum
|
||||
from app.models.chat_generation_task import ChatGenerationTask
|
||||
from app.models.module_generation_project import ModuleGenerationProject
|
||||
@@ -335,6 +336,8 @@ async def _soft_delete_steps_from_index(
|
||||
project: ModuleGenerationProject,
|
||||
start_index: int,
|
||||
deleted_at: datetime | None = None,
|
||||
refund_unfinished: bool = True,
|
||||
release_stats: dict[str, int] | None = None,
|
||||
) -> None:
|
||||
await _base_soft_delete_steps_from_index(
|
||||
db,
|
||||
@@ -343,6 +346,8 @@ async def _soft_delete_steps_from_index(
|
||||
config=FLOW_CONFIG,
|
||||
log_module_event=log_module_event,
|
||||
deleted_at=deleted_at,
|
||||
refund_unfinished=refund_unfinished,
|
||||
release_stats=release_stats,
|
||||
)
|
||||
|
||||
|
||||
@@ -1406,6 +1411,60 @@ async def handle_chat_generation_task_failed(db: AsyncSession, task: ChatGenerat
|
||||
await log_module_event(db, project=project, step=step, event_type=ModuleEventTypeEnum.CHAT_TASK_FAILED.value, message=project.error_message, detail={"chat_task_id": task.id})
|
||||
|
||||
|
||||
|
||||
_ACTIVE_DELETE_BLOCK_STATUSES = {
|
||||
ChatGenerationTaskStatus.PENDING.value,
|
||||
ChatGenerationTaskStatus.GENERATING.value,
|
||||
}
|
||||
_ACTIVE_DELETE_BLOCK_STAGES = {
|
||||
ChatGenerationPipelineStage.QUEUED.value,
|
||||
ChatGenerationPipelineStage.PREPARING.value,
|
||||
ChatGenerationPipelineStage.CREATING_PROVIDER_TASK.value,
|
||||
ChatGenerationPipelineStage.WAITING_REMOTE.value,
|
||||
ChatGenerationPipelineStage.POLLING.value,
|
||||
ChatGenerationPipelineStage.RESULT_READY.value,
|
||||
ChatGenerationPipelineStage.DOWNLOAD_QUEUED.value,
|
||||
ChatGenerationPipelineStage.DOWNLOADING.value,
|
||||
ChatGenerationPipelineStage.RETRY_WAITING.value,
|
||||
}
|
||||
|
||||
|
||||
async def _assert_project_has_no_active_chat_tasks_for_delete(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
project: ModuleGenerationProject,
|
||||
) -> None:
|
||||
"""用户主动删除项目/切片时不退款;如仍有异步生成任务进行中,直接拦截。"""
|
||||
step_result = await db.execute(
|
||||
select(ModuleGenerationStep.chat_task_id)
|
||||
.where(
|
||||
ModuleGenerationStep.project_id == project.id,
|
||||
ModuleGenerationStep.module == MODULE,
|
||||
ModuleGenerationStep.deleted_at.is_(None),
|
||||
ModuleGenerationStep.chat_task_id.is_not(None),
|
||||
)
|
||||
)
|
||||
chat_task_ids = [task_id for task_id in step_result.scalars().all() if task_id]
|
||||
if not chat_task_ids:
|
||||
return
|
||||
|
||||
task_result = await db.execute(
|
||||
select(ChatGenerationTask)
|
||||
.where(
|
||||
ChatGenerationTask.id.in_(chat_task_ids),
|
||||
ChatGenerationTask.deleted_at.is_(None),
|
||||
)
|
||||
.with_for_update()
|
||||
)
|
||||
active_tasks = []
|
||||
for task in task_result.scalars().all():
|
||||
if task.status in _ACTIVE_DELETE_BLOCK_STATUSES or (task.pipeline_stage in _ACTIVE_DELETE_BLOCK_STAGES):
|
||||
active_tasks.append(task.id)
|
||||
|
||||
if active_tasks:
|
||||
raise HTTPException(status_code=400, detail="当前拆镜复刻项目仍有生成中任务,暂不能删除")
|
||||
|
||||
|
||||
async def mark_shot_replicate_step_dispatch_failed(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
@@ -1462,13 +1521,45 @@ async def mark_shot_replicate_step_dispatch_failed(
|
||||
)
|
||||
|
||||
|
||||
async def delete_shot_replicate_project(db: AsyncSession, *, current_user: User, project_id: str) -> ShotReplicateDeleteOut:
|
||||
async def delete_shot_replicate_project(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
current_user: User,
|
||||
project_id: str,
|
||||
refund_unfinished: bool = False,
|
||||
) -> ShotReplicateDeleteOut:
|
||||
project = await _get_project_for_user(db, project_id=project_id, user=current_user, for_update=True)
|
||||
deleted_at = _now()
|
||||
release_stats: dict[str, int] = {"released_size_bytes": 0}
|
||||
|
||||
if not refund_unfinished:
|
||||
await _assert_project_has_no_active_chat_tasks_for_delete(db, project=project)
|
||||
|
||||
project.deleted_at = deleted_at
|
||||
await _soft_delete_steps_from_index(db, project=project, start_index=1, deleted_at=deleted_at)
|
||||
await log_module_event(db, project=project, event_type=ModuleEventTypeEnum.PROJECT_DELETED.value, message="软删除拆镜复刻项目")
|
||||
return ShotReplicateDeleteOut(message="项目已删除", project_id=project.id, deleted=True)
|
||||
await _soft_delete_steps_from_index(
|
||||
db,
|
||||
project=project,
|
||||
start_index=1,
|
||||
deleted_at=deleted_at,
|
||||
refund_unfinished=refund_unfinished,
|
||||
release_stats=release_stats,
|
||||
)
|
||||
await log_module_event(
|
||||
db,
|
||||
project=project,
|
||||
event_type=ModuleEventTypeEnum.PROJECT_DELETED.value,
|
||||
message="软删除拆镜复刻项目",
|
||||
detail={
|
||||
"refund_unfinished": refund_unfinished,
|
||||
"released_size_bytes": int(release_stats.get("released_size_bytes", 0)),
|
||||
},
|
||||
)
|
||||
return ShotReplicateDeleteOut(
|
||||
message="项目已删除",
|
||||
project_id=project.id,
|
||||
deleted=True,
|
||||
released_size_bytes=int(release_stats.get("released_size_bytes", 0)),
|
||||
)
|
||||
|
||||
|
||||
async def create_shot_replicate_project_from_segment(
|
||||
|
||||
Reference in New Issue
Block a user