CI / test (pull_request) Successful in 1m35s
问题:RIIN 商品级 goodsStatus 复用平台状态枚举,COMPLETE/PAUSE 无映射, .get() 返回 None 落库为 NULL,累计 206 万行(占 RIIN 商品 33.75%), 终态订单不再被 refresh_pending 刷新而长期滞留。该缺口继承自 inkreach-bi-auth-mng TS 版,且 TS 的 warnUnknown 告警在移植时被省略, 导致从未暴露。 修复: - RIIN_GOODS_STATUS_MAP 补 COMPLETE=已完成、PAUSE=暂停 - 对齐 TS 版 warnUnknown:四个状态映射函数对未知值告警(同值只报一次) - docs/sql:Goods.status 约束新增允许"暂停"(原约束拒绝,已在库执行) - scripts/backfill_riin_goods_status.py:存量 NULL 按"已发货"订单终态 近似回填(幂等、分批);"已关闭"与非终态订单走 by-orders 重拉真值 - tests/test_mappers.py:9 个单测全过;实单 GSU1S555400MFLL e2e 验证 4 行 NULL → 已完成/暂停
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
"""一次性回填:RIIN Goods.status 为 NULL 的历史行(终态"已发货"订单)。
|
|
|
|
背景:RIIN 商品级 goods_status 复用平台状态枚举,COMPLETE/PAUSE 此前无映射,
|
|
约 1/3 商品行 status 被写为 NULL(mappers.py 已补映射)。本脚本按订单终态
|
|
将近似值回填;"已关闭"与非终态订单不在此列,走 riin-by-orders 重拉取真值。
|
|
幂等:只更新 status IS NULL 的行。分批提交,避免长事务。
|
|
|
|
运行:uv run python scripts/backfill_riin_goods_status.py [--dry-run] [--batch N]
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
|
|
import psycopg2
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))
|
|
|
|
DEFAULT_BATCH = 50_000
|
|
|
|
SQL_COUNT = """
|
|
SELECT count(*) FROM "Goods" g
|
|
JOIN "Orders" o ON o."orderNo" = g."orderNo" AND o."createdAt" = g."createdAt"
|
|
WHERE o."systemName" = 'RIIN' AND o."systemStatus" = '已发货' AND g."status" IS NULL
|
|
"""
|
|
|
|
# ctid 分批:PostgreSQL 的 UPDATE 不支持 LIMIT,用子查询圈定每批行
|
|
SQL_BACKFILL_BATCH = """
|
|
UPDATE "Goods" g SET "status" = '已发货'
|
|
WHERE g.ctid IN (
|
|
SELECT g2.ctid FROM "Goods" g2
|
|
JOIN "Orders" o ON o."orderNo" = g2."orderNo" AND o."createdAt" = g2."createdAt"
|
|
WHERE o."systemName" = 'RIIN' AND o."systemStatus" = '已发货' AND g2."status" IS NULL
|
|
LIMIT %s
|
|
)
|
|
"""
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="回填 RIIN Goods.status NULL(已发货订单)")
|
|
parser.add_argument("--dry-run", action="store_true", help="只统计待回填行数,不写入")
|
|
parser.add_argument("--batch", type=int, default=DEFAULT_BATCH, help="每事务回填行数")
|
|
args = parser.parse_args()
|
|
|
|
conn = psycopg2.connect(os.environ["DB_DSN"])
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(SQL_COUNT)
|
|
(pending,) = cur.fetchone()
|
|
print(f"[backfill] 待回填(status IS NULL 且订单已发货): {pending} 行")
|
|
if args.dry_run or pending == 0:
|
|
return
|
|
|
|
total = 0
|
|
while True:
|
|
with conn.cursor() as cur:
|
|
cur.execute(SQL_BACKFILL_BATCH, (args.batch,))
|
|
updated = cur.rowcount
|
|
conn.commit()
|
|
total += updated
|
|
print(f"[backfill] 本批 {updated} 行,累计 {total}")
|
|
if updated < args.batch:
|
|
break
|
|
print(f"[backfill] 完成,共回填 {total} 行")
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|