chore: sync production runtime and docs

This commit is contained in:
2026-04-25 15:02:40 +08:00
parent cb518b431f
commit 1e44101eb2
50 changed files with 8575 additions and 2177 deletions
+105
View File
@@ -0,0 +1,105 @@
from __future__ import annotations
import argparse
import asyncio
import json
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional
PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
from backend.app.config import ensure_project_env_loaded
ensure_project_env_loaded()
from backend.app import database
from backend.app.services.dinsar_layout_migration_service import dinsar_layout_migration_service
from backend.app.services.manifest_inventory_service import manifest_inventory_service
from backend.app.services.result_catalog_service import result_catalog_service
from backend.app.services.root_registry_service import root_registry_service
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Normalize managed ENVI D-InSAR run layouts under DINSAR_PRODUCT_DIR."
)
parser.add_argument(
"--root-dir",
default=None,
help="Managed D-InSAR publish root. Defaults to settings.DINSAR_PRODUCT_DIR.",
)
parser.add_argument(
"--pair-key",
action="append",
default=None,
help="Only migrate the specified pair_key. Repeatable.",
)
parser.add_argument(
"--limit",
type=int,
default=None,
help="Stop after inspecting this many run directories.",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Inspect and report only. Do not move files or rewrite metadata.",
)
parser.add_argument(
"--skip-catalog-sync",
action="store_true",
help="Skip manifest inventory sync and catalog rebuild after migration.",
)
return parser.parse_args()
async def _sync_catalog() -> Dict[str, Any]:
database.init_db()
if database.AsyncSessionLocal is None:
raise RuntimeError("Database session factory is not initialized.")
root_sync = await root_registry_service.sync_from_settings()
async with database.AsyncSessionLocal() as db:
inventory_result = await manifest_inventory_service.sync_manifest_roots(db)
rebuild_result = await result_catalog_service.rebuild_catalog(
db,
full_rebuild=True,
)
return {
"root_registry": root_sync,
"manifest_inventory": inventory_result,
"catalog_rebuild": rebuild_result,
}
async def main_async() -> int:
args = parse_args()
result = dinsar_layout_migration_service.migrate_managed_envi_runs(
root_dir=args.root_dir,
pair_keys=args.pair_key,
limit=args.limit,
dry_run=args.dry_run,
)
should_sync_catalog = (
not args.dry_run
and not args.skip_catalog_sync
and int(result.get("migrated_count", 0) or 0) + int(result.get("rewritten_count", 0) or 0) > 0
and int(result.get("failed_count", 0) or 0) == 0
)
if should_sync_catalog:
result["post_sync"] = await _sync_catalog()
print(json.dumps(result, ensure_ascii=False, indent=2))
return 0 if int(result.get("failed_count", 0) or 0) == 0 else 1
def main() -> int:
return asyncio.run(main_async())
if __name__ == "__main__":
raise SystemExit(main())