Files
rar-autopass/tools/backup.py
Claude Agent 44f261e269 refactor: comentarii strict functionale, fara referinte PRD/stories
Curatare globala a comentariilor si docstring-urilor (app, tools, teste,
scripturi): eliminate referintele la PRD-uri, US-xxx, task-uri istorice si
review-uri; pastrata doar informatia functionala, formulata scurt. Regula
adaugata in CLAUDE.md (sectiunea Stil). Fara modificari de cod sau comportament.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 13:48:38 +00:00

80 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""Backup online SQLite — copie consistenta a bazei pe volum persistent.
SQLite in WAL NU se copiaza sigur cu `cp` (WAL-ul poate avea tranzactii necheckpoint-ate).
Folosim API-ul `Connection.backup` (online, consistent, fara oprirea worker-ului).
Utilizare:
python -m tools.backup # -> <db_dir>/backups/autopass-YYYYMMDD-HHMMSS.db
python -m tools.backup --out /path/snap.db # destinatie explicita
python -m tools.backup --keep 14 # pastreaza ultimele 14, sterge restul
Recomandat: rulat dintr-un cron pe gazda (ex. zilnic), tinta pe volum/montaj separat.
"""
from __future__ import annotations
import argparse
import sqlite3
import sys
from datetime import datetime, timezone
from pathlib import Path
from app.config import get_settings
def backup_db(src: Path, dest: Path) -> Path:
"""Backup online (consistent) din `src` in `dest`. Intoarce `dest`."""
dest.parent.mkdir(parents=True, exist_ok=True)
src_conn = sqlite3.connect(src)
try:
dst_conn = sqlite3.connect(dest)
try:
src_conn.backup(dst_conn)
finally:
dst_conn.close()
finally:
src_conn.close()
return dest
def prune(backup_dir: Path, keep: int) -> list[Path]:
"""Pastreaza cele mai noi `keep` snapshot-uri (dupa nume = timestamp), sterge restul."""
snaps = sorted(backup_dir.glob("autopass-*.db"), reverse=True)
removed = []
for old in snaps[keep:]:
old.unlink(missing_ok=True)
removed.append(old)
return removed
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Backup online SQLite gateway RAR AUTOPASS")
parser.add_argument("--out", type=Path, default=None, help="destinatie explicita (default: <db_dir>/backups/)")
parser.add_argument("--keep", type=int, default=0, help="pastreaza ultimele N snapshot-uri (0 = nu sterge)")
args = parser.parse_args(argv)
src = get_settings().db_path
if not src.exists():
print(f"eroare: baza {src} nu exista", file=sys.stderr)
return 1
if args.out is not None:
dest = args.out
else:
stamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
dest = src.parent / "backups" / f"autopass-{stamp}.db"
backup_db(src, dest)
print(f"backup -> {dest} ({dest.stat().st_size} bytes)")
if args.keep > 0:
removed = prune(dest.parent, args.keep)
if removed:
print(f"sterse {len(removed)} snapshot-uri vechi (pastrez {args.keep})")
return 0
if __name__ == "__main__":
sys.exit(main())