patristic-be / src /lib /system /migrate.py
Mario33333's picture
deploy: reader-access security hardening (feature/audiobook@06a5ed8)
7c2d250 verified
Raw
History Blame Contribute Delete
2.47 kB
"""CLI for backend migrations.
Usage:
python -m src.lib.system.migrate inventory --to cloud # merge (default)
python -m src.lib.system.migrate inventory --to cloud --mode replace # destructive
python -m src.lib.system.migrate vectors --to cloud
python -m src.lib.system.migrate vectors --to local --mode replace
Modes:
merge (default, safe) Add new rows/points; existing target rows untouched.
Idempotent — re-running produces the same end state.
replace (destructive) Wipe target completely, then copy from source.
"""
from __future__ import annotations
import argparse
from .migration import migrate_inventory, migrate_vectors
def main(argv: list[str] | None = None) -> int:
ap = argparse.ArgumentParser(description="Migrate data between local and cloud backends")
sub = ap.add_subparsers(dest="component", required=True)
inv = sub.add_parser("inventory", help="Migrate the inventory DB (SQLite <-> Turso)")
inv.add_argument("--to", required=True, choices=("local", "cloud"))
inv.add_argument("--mode", default="merge", choices=("merge", "replace"))
vec = sub.add_parser("vectors", help="Migrate Qdrant points (local <-> cloud)")
vec.add_argument("--to", required=True, choices=("local", "cloud"))
vec.add_argument("--collection", default=None, help="defaults to the active collection")
vec.add_argument("--mode", default="merge", choices=("merge", "replace"))
args = ap.parse_args(argv)
direction = "local_to_cloud" if args.to == "cloud" else "cloud_to_local"
if args.component == "inventory":
report = migrate_inventory(direction, mode=args.mode)
print(f"Inventory migration ({report.mode}) {direction}: "
f"{report.total_rows} rows in {report.elapsed_ms} ms")
for table, n in report.rows_per_table.items():
print(f" {table:20s} {n:>6}")
if report.skipped_tables:
print(f" skipped (log tables in merge mode): {', '.join(report.skipped_tables)}")
else:
report = migrate_vectors(direction, collection=args.collection, mode=args.mode)
print(f"Vector migration ({report.mode}) {direction}: "
f"collection {report.collection!r}, "
f"{report.points} points in {report.elapsed_ms} ms")
return 0
if __name__ == "__main__":
raise SystemExit(main())