Refine seller store implementation

This commit is contained in:
R524809
2026-08-31 14:37:28 +08:00
parent 957289f717
commit 2a667b4f3b
27 changed files with 1650 additions and 624 deletions
+43 -1
View File
@@ -26,6 +26,7 @@ from services.storage import get_storage
from services.suite_service import append_generated_asset
from services.tasks import TaskImage
from services.watermark import apply_watermark
from services.video_renderer import VideoRenderCancelled, render_slideshow
log = logging.getLogger("background.worker")
@@ -113,11 +114,52 @@ async def _process_watermark_item(claim: ClaimedItem) -> None:
await mark_item_failed(claim.item_id, str(exc))
async def _process_slideshow_video_item(claim: ClaimedItem) -> None:
"""一个视频任务只有一个子项;输入 URL 在提交时冻结,避免后续选择状态影响成片。"""
payload = claim.request_payload
sources = list(payload.get("sources") or [])
source_urls = [str(source.get("url") or "") for source in sources]
if not 2 <= len(source_urls) <= 5 or any(not url for url in source_urls):
await mark_item_failed(claim.item_id, "视频任务缺少 2–5 张可用图片")
return
try:
async def should_cancel() -> bool:
return not await job_can_write(claim.job_id)
rendered = await render_slideshow(source_urls, should_cancel=should_cancel)
if not await job_can_write(claim.job_id):
await mark_item_cancelled(claim.item_id)
return
key = f"products/{claim.product_id}/videos/{claim.job_id}/result.mp4"
result_url = await get_storage().save_bytes(rendered.data, key, "video/mp4")
async with get_session_factory()() as db:
from models import BackgroundJobItem
item = await db.get(BackgroundJobItem, uuid.UUID(claim.item_id))
if item is not None:
item.payload = {
**dict(item.payload),
"duration_seconds": rendered.duration_seconds,
"width": rendered.width,
"height": rendered.height,
"file_size_bytes": len(rendered.data),
}
await db.commit()
await mark_item_done(claim.item_id, result_url=result_url, source_url=None, watermark_config=None, generated_asset_id=None)
except VideoRenderCancelled:
await mark_item_cancelled(claim.item_id)
except Exception as exc: # noqa: BLE001
log.exception("后台轮播视频任务 %s/%s 执行失败", claim.job_id, claim.item_id)
await mark_item_failed(claim.item_id, str(exc))
async def process_item(claim: ClaimedItem) -> None:
"""推进一次子任务。外部模型未完成时只写 provider id 并退出,让出 Worker。"""
if claim.job_kind == "watermark_batch":
await _process_watermark_item(claim)
return
if claim.job_kind == "slideshow_video":
await _process_slideshow_video_item(claim)
return
if claim.job_kind not in {"image_suite", "image_edit"}:
await mark_item_failed(claim.item_id, f"Worker 暂不支持任务类型: {claim.job_kind}")
return
@@ -201,7 +243,7 @@ async def run_worker(*, once: bool = False, idle_seconds: float = 0.75) -> None:
log.warning("恢复了 %d 个过期后台任务租约", recovered)
log.info("后台 Worker 已启动:%s", owner)
while True:
claim = await claim_next_item(owner)
claim = await claim_next_item(owner, lease_seconds=get_settings().background_job_lease_seconds)
if claim is None:
if once:
return