Files
inquiry_robot/inquiry-agent/agent/jobs/pdf_job.py
T

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)