让成交卡等报价文件真正发出后再出现,并收紧 PDF 顶部留白,避免抬头被裁或空一截。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user