Spaces:
Running on Zero
Running on Zero
Download scripts/storage_maintenance.py from lothnic/precedentai: direct link, hf CLI and curl.
- Browser
- Download file 3.48 kB
-
https://huggingface.co/spaces/lothnic/precedentai/resolve/main/scripts/storage_maintenance.py
- Command line
-
hf download hf://spaces/lothnic/precedentai/scripts/storage_maintenance.py
-
curl -L -o storage_maintenance.py https://huggingface.co/spaces/lothnic/precedentai/resolve/main/scripts/storage_maintenance.py
3.48 kB
| """Run private application backup/restore and retention outside serving requests.""" | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| import os | |
| from datetime import UTC, datetime | |
| from pathlib import Path | |
| from shared.database import StorageUnavailable | |
| from shared.storage_ops import ( | |
| BackupError, | |
| backup, | |
| cleanup, | |
| key_file, | |
| prune_backups, | |
| read_backup, | |
| restore, | |
| ) | |
| ROOT = Path(__file__).resolve().parents[1] | |
| DEFAULT_KEY = ROOT / "deploy/.generated/precedent-backup.key" | |
| DEFAULT_BACKUPS = ROOT / "deploy/.generated/storage-backups" | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--key-file", type=Path, default=DEFAULT_KEY) | |
| subcommands = parser.add_subparsers(dest="operation", required=True) | |
| subcommands.add_parser( | |
| "init-key", help="Create a private encryption key; never print or overwrite it." | |
| ) | |
| export = subcommands.add_parser( | |
| "backup", help="Encrypt a consistent application-data snapshot." | |
| ) | |
| export.add_argument("--output", type=Path) | |
| for name in ("inspect", "restore"): | |
| command = subcommands.add_parser(name) | |
| command.add_argument("--backup", type=Path, required=True) | |
| maintenance = subcommands.add_parser("cleanup") | |
| maintenance.add_argument("--batch", type=int, default=500) | |
| pruning = subcommands.add_parser("prune-backups") | |
| pruning.add_argument("--directory", type=Path, default=DEFAULT_BACKUPS) | |
| args = parser.parse_args() | |
| try: | |
| if args.operation == "init-key": | |
| key_file(args.key_file, create=True) | |
| print(json.dumps({"status": "key_created", "path": str(args.key_file)})) | |
| return | |
| if args.operation == "inspect": | |
| document = read_backup(args.backup, key_file(args.key_file)) | |
| report = { | |
| "version": document["version"], | |
| "created_at": document["created_at"], | |
| "rows": {table: len(rows) for table, rows in document["data"].items()}, | |
| } | |
| elif args.operation == "prune-backups": | |
| report = prune_backups(args.directory, key_file(args.key_file)) | |
| else: | |
| dsn = os.environ.get("LEGAL_AI_QUOTA_DATABASE_URL") | |
| if not dsn: | |
| raise BackupError( | |
| "Set LEGAL_AI_QUOTA_DATABASE_URL privately in the operator environment." | |
| ) | |
| if args.operation == "cleanup": | |
| report = cleanup(dsn, batch=args.batch) | |
| elif args.operation == "backup": | |
| destination = args.output or DEFAULT_BACKUPS / datetime.now(UTC).strftime( | |
| "precedent-%Y%m%dT%H%M%S%fZ.pab" | |
| ) | |
| report = backup(dsn, destination, key_file(args.key_file)) | |
| report.update( | |
| path=str(destination), | |
| sha256=hashlib.sha256(destination.read_bytes()).hexdigest(), | |
| ) | |
| else: | |
| report = restore(dsn, args.backup, key_file(args.key_file)) | |
| print(json.dumps({"operation": args.operation, **report})) | |
| except (BackupError, StorageUnavailable) as exc: | |
| raise SystemExit(str(exc)) from None | |
| except (OSError, ImportError): | |
| raise SystemExit( | |
| "Storage maintenance failed. Check private file access and the storage/ops extras." | |
| ) from None | |
| if __name__ == "__main__": | |
| main() | |