""" Backup de la tabla corpus_chunks a un archivo CSV restaurable. Vuelca TODA la tabla (todas las corpus_version, incluido el embedding) vía COPY ... TO STDOUT WITH CSV HEADER. El archivo queda en backend/backups/ con timestamp. Read-only sobre la DB: no muta nada. Restore (manual, cuando haga falta): COPY corpus_chunks FROM '' WITH CSV HEADER; -- previo TRUNCATE corpus_chunks; si querés reemplazo total. Uso: python -m scripts.backup_corpus """ import os import sys from datetime import datetime from pathlib import Path import psycopg2 from dotenv import load_dotenv load_dotenv() DATABASE_URL = os.getenv("DATABASE_URL") BACKUP_DIR = Path("backups") def main(): if not DATABASE_URL: print("ERROR: DATABASE_URL no configurada en .env") sys.exit(1) BACKUP_DIR.mkdir(exist_ok=True) ts = datetime.now().strftime("%Y%m%d_%H%M%S") out_path = BACKUP_DIR / f"corpus_chunks_{ts}.csv" conn = psycopg2.connect(DATABASE_URL) try: with conn.cursor() as cur: cur.execute("SELECT COUNT(*) FROM corpus_chunks") total = cur.fetchone()[0] cur.execute( "SELECT corpus_version, COUNT(*) FROM corpus_chunks " "GROUP BY corpus_version ORDER BY corpus_version" ) by_version = cur.fetchall() print(f"Tabla corpus_chunks: {total} filas") for ver, n in by_version: print(f" {ver}: {n}") with conn.cursor() as cur, open(out_path, "w", encoding="utf-8", newline="") as f: cur.copy_expert("COPY corpus_chunks TO STDOUT WITH CSV HEADER", f) finally: conn.close() size_mb = out_path.stat().st_size / (1024 * 1024) print(f"\nBackup OK -> {out_path} ({size_mb:.1f} MB, {total} filas)") if __name__ == "__main__": main()