HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1"""Database backups (pg_dump custom format, gzip-compressed by pg_dump) into AIA_DATA_DIR/backups. Off-node copies: scripts/backup-offnode.sh.2The dataset is worth more than the code — keep 30 dailies."""3from __future__ import annotations45import os6import shutil7import subprocess8from datetime import UTC, datetime9from pathlib import Path10from urllib.parse import urlparse1112from aiatlas.config import settings131415def _pg_dump() -> str:16 for candidate in ("/opt/homebrew/opt/postgresql@17/bin/pg_dump", "/opt/homebrew/bin/pg_dump", "/usr/local/bin/pg_dump", "pg_dump"):17 if shutil.which(candidate) or os.path.exists(candidate):18 return candidate19 raise RuntimeError("pg_dump not found")202122def backup_database(keep: int = 30) -> Path:23 settings.ensure_dirs()24 url = urlparse(settings.sync_database_url)25 stamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")26 out = settings.backups_dir / f"aiatlas-{stamp}.dump"27 env = dict(os.environ)28 if url.password:29 env["PGPASSWORD"] = url.password30 cmd = [_pg_dump(), "-Fc", "-Z", "6", "-f", str(out), "-h", url.hostname or "127.0.0.1", "-p", str(url.port or 5432), "-U", url.username or "aiatlas",31 (url.path or "/aiatlas").lstrip("/")]32 subprocess.run(cmd, check=True, env=env, timeout=3600)33 dumps = sorted(settings.backups_dir.glob("aiatlas-*.dump"))34 for old in dumps[:-keep]:35 old.unlink(missing_ok=True)36 return out373839__all__ = ["backup_database"]40