81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
"""
|
|
报价 PDF 任务壳:入队后由 LibreOffice **单槽**消费。
|
|
|
|
本文件职责:enqueue_pdf_job / process 调用 LibreOfficeConverter。
|
|
禁止:在 http_jobs 槽跑 soffice;禁止回调线程转换。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from dataclasses import dataclass
|
|
from typing import Any, Optional
|
|
|
|
from agent.jobs.libreoffice import LibreOfficeConverter, LibreOfficeResult
|
|
from agent.redis_coord import get_redis_runtime, try_acquire_idempotency
|
|
from agent.redis_coord.keys import STREAM_PDF
|
|
from agent.redis_coord.runtime import RedisRuntime
|
|
from agent.redis_coord.stream_queue import StreamQueue
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclass
|
|
class PdfEnqueueResult:
|
|
accepted: bool
|
|
entry_id: str = ""
|
|
reason: str = ""
|
|
|
|
|
|
def pdf_stream(redis: Optional[RedisRuntime] = None) -> StreamQueue:
|
|
rt = redis or get_redis_runtime()
|
|
return StreamQueue(client=rt.client, stream_suffix=STREAM_PDF)
|
|
|
|
|
|
def enqueue_pdf_job(
|
|
*,
|
|
xlsx_path: str,
|
|
inquiry_no: str = "",
|
|
quote_version: int = 0,
|
|
idempotency_key: str = "",
|
|
redis: Optional[RedisRuntime] = None,
|
|
) -> PdfEnqueueResult:
|
|
"""Excel→PDF 任务入队;真正转换只在 LibreOffice 槽。"""
|
|
rt = redis or get_redis_runtime()
|
|
q = pdf_stream(rt)
|
|
q.ensure_group()
|
|
if idempotency_key:
|
|
ok = try_acquire_idempotency(
|
|
rt.client,
|
|
scope="pdf",
|
|
idempotency_key=idempotency_key,
|
|
ttl_seconds=600,
|
|
)
|
|
if not ok:
|
|
return PdfEnqueueResult(accepted=False, reason="duplicate_idempotency_key")
|
|
payload = {
|
|
"xlsx_path": xlsx_path,
|
|
"inquiry_no": inquiry_no,
|
|
"quote_version": quote_version,
|
|
}
|
|
entry_id = q.enqueue(payload=payload, idempotency_key=idempotency_key)
|
|
logger.info("pdf.enqueue id=%s inquiry=%s", entry_id, inquiry_no or "-")
|
|
return PdfEnqueueResult(accepted=True, entry_id=entry_id)
|
|
|
|
|
|
def process_pdf_job(
|
|
data: dict[str, Any],
|
|
*,
|
|
converter: Optional[LibreOfficeConverter] = None,
|
|
) -> LibreOfficeResult:
|
|
"""
|
|
处理一条 PDF 任务(调用方必须已占用 libreoffice 槽)。
|
|
|
|
缺 xlsx_path 或本机无 soffice 时返回 ok=False,不抛崩 Worker。
|
|
"""
|
|
path = str(data.get("xlsx_path") or "")
|
|
conv = converter or LibreOfficeConverter.from_settings()
|
|
if not path:
|
|
return LibreOfficeResult(ok=False, error="missing_xlsx_path")
|
|
return conv.convert_xlsx_to_pdf(path)
|