Files
shaguabijia-app-server/scripts/backfill_comparison_savings.py
T
2026-07-28 20:11:30 +08:00

104 lines
3.0 KiB
Python

"""分批回填历史比价节省金额。
默认只预览,不写库:
python -m scripts.backfill_comparison_savings
确认预览后实际执行:
python -m scripts.backfill_comparison_savings --apply
中断后可从日志最后一个 last_id 继续:
python -m scripts.backfill_comparison_savings --apply --after-id 12345
"""
from __future__ import annotations
import argparse
from app.db.session import SessionLocal
from app.services.comparison_savings_backfill import (
latest_success_id,
repair_comparison_savings_batch,
)
def _positive_int(value: str) -> int:
parsed = int(value)
if parsed <= 0:
raise argparse.ArgumentTypeError("必须为正整数")
return parsed
def _non_negative_int(value: str) -> int:
parsed = int(value)
if parsed < 0:
raise argparse.ArgumentTypeError("不能为负数")
return parsed
def main() -> None:
parser = argparse.ArgumentParser(
description="按完整购物篮口径分批回填历史比价节省金额(默认 dry-run)"
)
parser.add_argument("--apply", action="store_true", help="实际写库;默认仅预览")
parser.add_argument("--batch-size", type=_positive_int, default=500)
parser.add_argument(
"--after-id",
type=_non_negative_int,
default=0,
help="只处理大于该主键的记录,用于断点续跑",
)
parser.add_argument(
"--max-id",
type=_non_negative_int,
help="固定扫描上界;不传则启动时取成功记录最大主键",
)
parser.add_argument(
"--max-batches",
type=_positive_int,
help="本次最多处理多少批,便于灰度限量执行",
)
args = parser.parse_args()
with SessionLocal() as db:
max_id = args.max_id if args.max_id is not None else latest_success_id(db)
mode = "APPLY" if args.apply else "DRY-RUN"
after_id = args.after_id
scanned = 0
changed = 0
batches = 0
print(
f"comparison savings backfill mode={mode} "
f"after_id={after_id} max_id={max_id} batch_size={args.batch_size}"
)
while after_id < max_id:
with SessionLocal() as db:
result = repair_comparison_savings_batch(
db,
after_id=after_id,
max_id=max_id,
batch_size=args.batch_size,
apply=args.apply,
)
batches += 1
scanned += result.scanned
changed += result.changed
after_id = result.last_id
print(
f"batch={batches} scanned={result.scanned} changed={result.changed} "
f"last_id={result.last_id} done={result.done}"
)
if result.done or (
args.max_batches is not None and batches >= args.max_batches
):
break
print(
f"completed mode={mode} batches={batches} scanned={scanned} "
f"changed={changed} last_id={after_id} max_id={max_id}"
)
if __name__ == "__main__":
main()