Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Copy a stable operator snapshot without stopping or locking the evaluator.""" | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| from pathlib import Path | |
| import shutil | |
| import sys | |
| import tempfile | |
| import time | |
| ROOT = Path(__file__).resolve().parents[1] | |
| sys.path.insert(0, str(ROOT / "src")) | |
| from tsfm_bench.remote_state import HANDOFF_ROOTS, utc_now | |
| def inventory(root): | |
| result = {} | |
| for prefix in HANDOFF_ROOTS: | |
| for path in (root / prefix).rglob("*"): | |
| if path.is_symlink(): | |
| raise ValueError(f"Refusing symlink: {path.relative_to(root)}") | |
| if path.is_file(): | |
| stat = path.stat() | |
| result[path.relative_to(root)] = (stat.st_size, stat.st_mtime_ns, stat.st_ino) | |
| return result | |
| def snapshot(root, destination): | |
| if destination.exists(): | |
| raise ValueError("Snapshot destination must not exist") | |
| before = inventory(root) | |
| with tempfile.TemporaryDirectory(prefix="livehouse-copy-", dir=destination.parent) as temp: | |
| stage = Path(temp) / "snapshot" | |
| stage.mkdir() | |
| for rel in sorted(before): | |
| target = stage / rel | |
| target.parent.mkdir(parents=True, exist_ok=True) | |
| shutil.copy2(root / rel, target) | |
| if inventory(root) != before: | |
| raise RuntimeError("Operator changed during copying; retry between evaluation cycles") | |
| record = {"created_at":utc_now(), "files":len(before), | |
| "source_bytes":sum(stat[0] for stat in before.values())} | |
| (stage / ".snapshot.json").write_text(json.dumps(record, indent=2) + "\n") | |
| stage.rename(destination) | |
| return record | |
| def main(): | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--destination", type=Path, required=True) | |
| args = parser.parse_args() | |
| destination = args.destination.resolve() | |
| destination.parent.mkdir(parents=True, exist_ok=True) | |
| for attempt in range(3): | |
| try: | |
| print(json.dumps(snapshot(ROOT, destination)), flush=True) | |
| return | |
| except (FileNotFoundError, RuntimeError) as exc: | |
| if attempt == 2: | |
| raise | |
| print(f"{exc}; retrying in 20 seconds", flush=True) | |
| time.sleep(20) | |
| if __name__ == "__main__": | |
| main() | |