104 lines
3.0 KiB
Python
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()
|