#!/usr/bin/env python3 """Backfill du statut « présumée fermée » depuis l'historique sync_log. Le mécanisme durable vit dans fabrika/ingest.py (compteur fail_streak, seuil CLOSE_AFTER_FAILS, réintégration automatique au premier sync réussi). Ce script rejoue l'historique existant : pour chaque boutique activée, on compte les échecs consécutifs depuis le dernier sync réussi ; au-delà du seuil, statut appliqué + produits dépubliés (réversible). Usage : .venv/bin/python scripts/backfill_closures.py [--dry-run] """ import argparse import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) from fabrika import db # noqa: E402 from fabrika.ingest import CLOSE_AFTER_FAILS # noqa: E402 def main(): ap = argparse.ArgumentParser() ap.add_argument("--dry-run", action="store_true") args = ap.parse_args() con = db.connect() stores = con.execute( "SELECT id, name, product_count FROM stores " "WHERE enabled=1 AND catalog_endpoint<>''").fetchall() closed, updated = [], 0 for sid, name, pc in stores: rows = con.execute( "SELECT status FROM sync_log WHERE store_id=? " "ORDER BY ts DESC LIMIT 100", (sid,)).fetchall() streak = 0 for (status,) in rows: if status == "error": streak += 1 elif status == "ok": break # presumed_closed / autres statuts : neutres con.execute("UPDATE stores SET fail_streak=? WHERE id=?", (streak, sid)) updated += 1 if streak >= CLOSE_AFTER_FAILS: closed.append((sid, name, streak, pc)) if not args.dry_run: con.execute("UPDATE stores SET presumed_closed=1, product_count=0 " "WHERE id=?", (sid,)) con.execute("UPDATE products SET active=0 WHERE store_id=?", (sid,)) db.log_sync(con, sid, 0, 0, 0, 0, "presumed_closed", f"backfill historique : {streak} échecs consécutifs") if not args.dry_run: con.commit() con.close() print(f"fail_streak recalculé pour {updated} boutiques") print(f"présumées fermées ({'dry-run' if args.dry_run else 'appliqué'}) : " f"{len(closed)}") for sid, name, streak, pc in closed: print(f" - {sid} «{name}» : {streak} échecs consécutifs, " f"{pc} produits dépubliés") if __name__ == "__main__": main()