让成交卡等报价文件真正发出后再出现,并收紧 PDF 顶部留白,避免抬头被裁或空一截。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-15 10:36:55 +08:00
co-authored by Cursor
parent cb3bf5238b
commit a7a8487eb3
22 changed files with 1630 additions and 126 deletions
+51 -1
View File
@@ -190,6 +190,26 @@ class PostgresMessageStore:
logger.exception("pg outbox 入队失败")
raise
def has_outbound_dedupe(self, prefix: str) -> bool:
"""去重键是否已出过站(前缀匹配)。跨进程看成交卡/文件是否已发。"""
head = (prefix or "").strip()
if not head:
return False
try:
with connect_psycopg(self._dsn) as conn:
row = conn.execute(
"""
SELECT 1 FROM agent_outbox
WHERE dedupe_key LIKE %s
LIMIT 1
""",
(head + "%",),
).fetchone()
return bool(row)
except Exception:
logger.exception("查 outbox 去重前缀失败 prefix=%s", head)
return False
def claim_outbound(self) -> Optional[OutboxItem]:
timeout = int(self._claim_timeout)
with connect_psycopg(self._dsn) as conn:
@@ -203,7 +223,7 @@ class PostgresMessageStore:
AND claimed_at IS NOT NULL
AND claimed_at < NOW() - (%s || ' seconds')::interval
)
ORDER BY created_at
ORDER BY created_at ASC, id ASC
FOR UPDATE SKIP LOCKED
LIMIT 1
)
@@ -294,6 +314,36 @@ class PostgresMessageStore:
def wait_outbox(self, timeout: float = 1.0) -> None:
self._outbox_event.wait(timeout=timeout)
def wait_outbound_done(self, item_id: str, timeout_sec: float = 12.0) -> bool:
"""
等到指定出站已发送完成或失败。
查价前先等询价确认发出,避免暂无报价卡抢先。只等这一条。
"""
raw = (item_id or "").strip()
if not raw:
return False
started = time.time()
deadline = started + max(0.1, float(timeout_sec))
saw_claim = False
while time.time() < deadline:
with connect_psycopg(self._dsn) as conn:
row = conn.execute(
"SELECT state FROM agent_outbox WHERE id = %s",
(raw,),
).fetchone()
state = str(row[0] or "") if row else ""
if state in {"done", "failed"}:
return state == "done"
if state == "claimed":
saw_claim = True
if not saw_claim and state == "pending" and time.time() - started >= 0.4:
return True
if not state and time.time() - started >= 0.3:
return True
self._outbox_event.wait(0.05)
return False
def stats(self) -> dict[str, Any]:
with connect_psycopg(self._dsn) as conn:
inbox = conn.execute(