feat: add durable Core Hub absorption runtime
This commit is contained in:
parent
7e1ec03f0c
commit
8ab1d0c09a
20 changed files with 2423 additions and 15 deletions
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
import argparse
|
||||
import json
|
||||
from importlib.resources import files
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
|
||||
from hub_core.mcp import HubCoreMCPServer
|
||||
|
|
@ -28,6 +29,21 @@ def build_parser(settings: RuntimeSettings | None = None) -> argparse.ArgumentPa
|
|||
migrate.add_argument("revision", nargs="?", default="head")
|
||||
migrate.add_argument("--database-url", default=resolved.database_url)
|
||||
|
||||
migration = commands.add_parser("migration", help="Export, validate, or import migration bundles")
|
||||
migration_commands = migration.add_subparsers(dest="migration_command", required=True)
|
||||
migration_validate = migration_commands.add_parser("validate")
|
||||
migration_validate.add_argument("bundle", type=Path)
|
||||
migration_validate.add_argument("--output", type=Path)
|
||||
migration_import = migration_commands.add_parser("import")
|
||||
migration_import.add_argument("bundle", type=Path)
|
||||
migration_import.add_argument("--database-url", default=resolved.database_url)
|
||||
migration_import.add_argument("--dry-run", action="store_true")
|
||||
migration_import.add_argument("--output", type=Path)
|
||||
migration_export = migration_commands.add_parser("export")
|
||||
migration_export.add_argument("--database-url", default=resolved.database_url)
|
||||
migration_export.add_argument("--source-revision")
|
||||
migration_export.add_argument("--output", type=Path, required=True)
|
||||
|
||||
conformance = commands.add_parser(
|
||||
"conformance",
|
||||
help="Run the implemented Tier 2/3 profile against an HTTP runtime",
|
||||
|
|
@ -53,6 +69,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|||
raise SystemExit("hub-core migrate requires --database-url or HUB_CORE_DATABASE_URL")
|
||||
_run_migrations(args.database_url, args.revision)
|
||||
return 0
|
||||
if args.command == "migration":
|
||||
return _run_migration(args)
|
||||
if args.command == "conformance":
|
||||
return _run_conformance(args.base_url, args.timeout, args.as_json)
|
||||
raise AssertionError(f"Unhandled command {args.command}")
|
||||
|
|
@ -96,5 +114,38 @@ def _run_conformance(base_url: str, timeout: float, as_json: bool) -> int:
|
|||
return 0 if report.passed else 1
|
||||
|
||||
|
||||
def _run_migration(args: argparse.Namespace) -> int:
|
||||
import asyncio
|
||||
|
||||
from hub_core.runtime.migration import (
|
||||
export_bundle,
|
||||
import_bundle,
|
||||
load_bundle,
|
||||
validate_bundle,
|
||||
)
|
||||
from hub_core.runtime.postgres_store import PostgresPortStore
|
||||
|
||||
if args.migration_command == "validate":
|
||||
report = validate_bundle(load_bundle(args.bundle))
|
||||
else:
|
||||
if not args.database_url:
|
||||
raise SystemExit("migration command requires --database-url or HUB_CORE_DATABASE_URL")
|
||||
store = PostgresPortStore.from_url(args.database_url)
|
||||
async def run() -> dict:
|
||||
try:
|
||||
if args.migration_command == "import":
|
||||
return await import_bundle(store, load_bundle(args.bundle), dry_run=args.dry_run)
|
||||
return await export_bundle(store, source_revision=args.source_revision)
|
||||
finally:
|
||||
await store.aclose()
|
||||
report = asyncio.run(run())
|
||||
rendered = json.dumps(report, indent=2, sort_keys=True)
|
||||
if args.output:
|
||||
args.output.write_text(rendered + "\n")
|
||||
else:
|
||||
print(rendered)
|
||||
return 0 if report.get("ok", True) else 1
|
||||
|
||||
|
||||
def _sync_database_url(database_url: str) -> str:
|
||||
return database_url.replace("postgresql+asyncpg://", "postgresql+psycopg2://")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue