mirror of
https://github.com/MemeMeow-Studio/MemeMeow.git
synced 2026-10-26 12:03:07 +08:00
99 lines
4.2 KiB
Python
99 lines
4.2 KiB
Python
"""公共核心图片处理批量提交 HTTP 边界。
|
|
|
|
本模块负责分页枚举当前 scope 图片、读取 metadata 输入、提交或复用处理 Job 以及逐项
|
|
错误投影;Worker、Repository、scope environment、配置规范化和路由注册由入口通过 callback
|
|
注入,不反向依赖 ``api.py`` 或 Server 入口。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable, Mapping
|
|
from typing import Any
|
|
|
|
from fastapi import HTTPException, Request
|
|
|
|
from backend.database import DatabaseError
|
|
from backend.image_processing import ImageProcessingError
|
|
from backend.metadata import MetadataError
|
|
|
|
|
|
ProcessingWorkerProvider = Callable[[Request], Any]
|
|
NormalizeOptions = Callable[..., Any]
|
|
ProcessingRepositoryProvider = Callable[[Request], Any]
|
|
MetadataServiceProvider = Callable[[Request], Any]
|
|
EnvironmentProvider = Callable[[Request], Any]
|
|
ProcessingConfigProvider = Callable[[Request], Mapping[str, object]]
|
|
ErrorFactory = Callable[[int, str, str], HTTPException]
|
|
|
|
|
|
async def process_image_library(
|
|
request: Request,
|
|
payload: Any,
|
|
*,
|
|
page: int,
|
|
page_size: int,
|
|
processing_worker: ProcessingWorkerProvider,
|
|
normalize_processing_options: NormalizeOptions,
|
|
processing_repository: ProcessingRepositoryProvider,
|
|
metadata_service: MetadataServiceProvider,
|
|
environment: EnvironmentProvider,
|
|
processing_config: ProcessingConfigProvider,
|
|
error: ErrorFactory,
|
|
) -> dict[str, object]:
|
|
"""分页枚举当前 scope 图片并逐图提交或复用处理 Job。
|
|
|
|
输入是已由入口校验的联网策略、auto-name 和分页参数;输出保留旧的逐图 Job 摘要、
|
|
复用标志、总数和分页字段。调用场景是图片工作区批量处理请求,任何单图异常只影响
|
|
当前结果,不阻止同页其它 Meme。
|
|
"""
|
|
worker = processing_worker(request)
|
|
if worker is None:
|
|
raise error(503, "image_processing_unavailable", "图片处理服务当前不可用")
|
|
try:
|
|
options = normalize_processing_options(
|
|
request,
|
|
reverse_image_policy=payload.reverse_image_policy,
|
|
auto_name=payload.auto_name,
|
|
)
|
|
except ImageProcessingError as exc:
|
|
raise error(503 if exc.code == "reverse_image_unavailable" else 400, exc.code, "图片处理选项无效或服务不可用") from exc
|
|
|
|
repository = processing_repository(request)
|
|
with environment(request) as database_environment:
|
|
memes = database_environment.memes.list(page=page, page_size=page_size)
|
|
total = database_environment.memes.count()
|
|
results: list[dict[str, object]] = []
|
|
for meme in memes:
|
|
try:
|
|
latest = repository.latest_for_target(meme.id, meme.sha256)
|
|
image_service = metadata_service(request)
|
|
image = image_service.blob_store.resolve(meme.storage_key)
|
|
embedding_record = image_service.embedding_record(image)
|
|
snapshot = worker.submit(
|
|
meme.id,
|
|
meme.sha256,
|
|
metadata_hash=embedding_record.get("metadata_hash") if isinstance(embedding_record, Mapping) else None,
|
|
config=processing_config(request),
|
|
reverse_image_policy=options.reverse_image_policy,
|
|
auto_name=options.auto_name,
|
|
explicit_retry=latest is not None and latest.status in {"failed", "blocked", "unknown_execution"},
|
|
)
|
|
results.append(
|
|
{
|
|
"meme_id": str(meme.id),
|
|
"job_id": snapshot.job_id,
|
|
"processing_job_id": snapshot.job_id,
|
|
"submission_mode": "pipeline",
|
|
"status": snapshot.status,
|
|
"reused": latest is not None and snapshot.job_id == latest.job_id,
|
|
}
|
|
)
|
|
except ImageProcessingError as exc:
|
|
results.append({"meme_id": str(meme.id), "error": exc.code})
|
|
except (DatabaseError, MetadataError, RuntimeError):
|
|
results.append({"meme_id": str(meme.id), "error": "image_processing_failed"})
|
|
return {"results": results, "count": len(results), "total": total, "page": page, "page_size": page_size}
|
|
|
|
|
|
__all__ = ["process_image_library"]
|