Files
meijiaka-zy/python-api/app/scheduler/handlers/copy_handler.py
T

121 lines
4.9 KiB
Python

"""
Copy 任务处理器
==============
管理 AnyToCopy 文案提取的提交与轮询。
"""
import logging
from typing import Any
from app.scheduler.handlers.base import AsyncHandler
from app.scheduler.models import StateChange
from app.scheduler.registry import JobRegistry
from app.scheduler.slot_manager import SlotManager
from app.services.anytocopy_service import get_anytocopy_service
logger = logging.getLogger(__name__)
SLOT_KEY = "anytocopy:slots"
MAX_SLOTS = 5
class CopyHandler(AsyncHandler):
name = "copy"
slot_key = SLOT_KEY
max_slots = MAX_SLOTS
async def tick(
self, jobs: list[Any], registry: JobRegistry, slots: SlotManager
) -> list[StateChange]:
changes: list[StateChange] = []
for job in jobs:
params = job.params or {}
anytocopy_task_id = params.get("anytocopy_task_id")
video_url = params.get("url", params.get("video_url", ""))
if anytocopy_task_id:
try:
service = get_anytocopy_service()
result = await service.query_task(anytocopy_task_id)
if result.get("code") != 200:
continue
data = result.get("data", {})
status = data.get("status")
if status == "SUCCESS":
result_data = {
"video_url": video_url,
"title": data.get("title", ""),
"content": data.get("content", ""),
"text_content": data.get("textContent", ""),
"platform": data.get("platform", ""),
"duration": data.get("duration", 0),
}
await slots.release(SLOT_KEY, job.job_id)
changes.append(
StateChange(job_id=job.job_id, field_path="status", value="completed")
)
changes.append(
StateChange(
job_id=job.job_id, field_path="message", value="文案提取完成"
)
)
changes.append(
StateChange(job_id=job.job_id, field_path="completed", value=1)
)
changes.append(StateChange(job_id=job.job_id, field_path="total", value=1))
changes.append(
StateChange(job_id=job.job_id, field_path="result", value=result_data)
)
elif status in ("FAILED", "FAILURE"):
await slots.release(SLOT_KEY, job.job_id)
changes.append(
StateChange(job_id=job.job_id, field_path="status", value="failed")
)
changes.append(
StateChange(
job_id=job.job_id,
field_path="message",
value=f"提取失败: {data.get('errorMessage', '未知错误')}",
)
)
changes.append(
StateChange(
job_id=job.job_id,
field_path="error",
value=data.get("errorMessage", ""),
)
)
except Exception as e:
logger.error(f"[Copy {job.job_id}] poll error: {e}")
continue
acquired = await slots.acquire(SLOT_KEY, job.job_id, MAX_SLOTS)
if not acquired:
continue
try:
service = get_anytocopy_service()
submit_result = await service.submit_task(video_url)
if submit_result.get("code") != 200:
raise Exception(f"提交失败: {submit_result.get('msg')}")
anytocopy_task_id = submit_result["data"]
params["anytocopy_task_id"] = anytocopy_task_id
changes.append(StateChange(job_id=job.job_id, field_path="params", value=params))
changes.append(
StateChange(job_id=job.job_id, field_path="message", value="文案提取任务已提交")
)
except Exception as e:
await slots.release(SLOT_KEY, job.job_id)
changes.append(StateChange(job_id=job.job_id, field_path="status", value="failed"))
changes.append(
StateChange(job_id=job.job_id, field_path="message", value=str(e)[:200])
)
changes.append(
StateChange(job_id=job.job_id, field_path="error", value=str(e)[:500])
)
return changes