feat: 接入企微智能机器人——异常报警/数据核验日报/设备健康日报

- flows/shared/wecom.py: WSClient 按需连接(连接→认证→发送→断开),全容错,超长分段
- flows/monitor/alert_failure.py: Prefect 事件触发(Failed/Crashed→run deployment),发群报警
- flows/monitor/daily_report.py: 每日 18:30 近7天 RIIN/SDS 核验(复用 verify)+商品完整性+OCR+失败回顾
- flows/monitor/device_check.py: 每日 09:00 内存/磁盘/GPU(80%阈值)+Docker 容器异常+服务探活
- db.py: 新增 get_goods_integrity/ping; compose worker 挂载 docker.sock+/:/host:ro+GPU
- scripts/wecom_capture_chatid.py: 一次性捕获群 chat_id 工具
This commit is contained in:
yeuimu
2026-08-27 09:40:53 +00:00
parent b9e0bc42be
commit 1d0da2a00b
12 changed files with 836 additions and 0 deletions
+45
View File
@@ -86,6 +86,51 @@ class SyncDB:
row = cur.fetchone()
return int(row[0]) if row else 0
def get_goods_integrity(self, system_name: str, start: datetime, end: datetime) -> dict[str, int]:
"""商品数据完整性(与核验同一时间窗,按 orderedAt):
- orders: 窗口内订单数
- goods: 窗口内商品行数
- zeroGoodsOrders: 窗口内没有任何商品行的订单数(可疑缺拉)
- goodsNoName: 窗口内商品 itemName 为空的行数
- orphanGoods: 全库没有对应订单的商品行数(脏数据)
"""
with self._conn() as conn:
with conn.cursor() as cur:
cur.execute(
'SELECT COUNT(*), '
'COALESCE(SUM(CASE WHEN NOT EXISTS ('
' SELECT 1 FROM "Goods" g WHERE g."orderNo"=o."orderNo" AND g."createdAt"=o."createdAt"'
') THEN 1 ELSE 0 END), 0) '
'FROM "Orders" o WHERE o."systemName"=%s AND o."orderedAt">=%s AND o."orderedAt"<%s',
(system_name, start, end),
)
orders, zero_goods = cur.fetchone()
cur.execute(
'SELECT COUNT(*), COALESCE(SUM(CASE WHEN "itemName" IS NULL OR "itemName"=\'\' '
'THEN 1 ELSE 0 END), 0) FROM "Goods" g JOIN "Orders" o '
'ON g."orderNo"=o."orderNo" AND g."createdAt"=o."createdAt" '
'WHERE o."systemName"=%s AND o."orderedAt">=%s AND o."orderedAt"<%s',
(system_name, start, end),
)
goods, no_name = cur.fetchone()
cur.execute(
'SELECT COUNT(*) FROM "Goods" g WHERE NOT EXISTS '
'(SELECT 1 FROM "Orders" o WHERE o."orderNo"=g."orderNo")',
)
orphan = cur.fetchone()[0]
return {
"orders": int(orders), "goods": int(goods),
"zeroGoodsOrders": int(zero_goods), "goodsNoName": int(no_name), "orphanGoods": int(orphan),
}
def ping(self) -> str:
"""连通性检查,返回 PG 版本号(供监控探活)。"""
with self._conn() as conn:
with conn.cursor() as cur:
cur.execute("SELECT version()")
row = cur.fetchone()
return (row[0] or "").split(",")[0] if row else ""
def get_orders_with_100_prefix(self, system_name: str, statuses: list[str]) -> list[tuple[str, datetime]]:
with self._conn() as conn:
with conn.cursor() as cur: