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
|
|
@ -1,9 +1,12 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI, Response, status
|
||||
|
||||
from hub_core import __version__
|
||||
from hub_core.runtime.config import RuntimeSettings
|
||||
from hub_core.runtime.compat import SQLCompatibilityStore, create_compatibility_router
|
||||
from hub_core.runtime.models import HealthResponse, ReadinessResponse
|
||||
from hub_core.runtime.ports import create_ports_router
|
||||
from hub_core.runtime.store import InMemoryPortStore, PortStore
|
||||
|
|
@ -17,37 +20,66 @@ def create_app(
|
|||
) -> FastAPI:
|
||||
resolved_settings = settings or RuntimeSettings.from_env()
|
||||
resolved_store = port_store or _create_store(resolved_settings)
|
||||
owns_store = port_store is None
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_: FastAPI):
|
||||
yield
|
||||
if owns_store and (closer := getattr(resolved_store, "aclose", None)):
|
||||
await closer()
|
||||
|
||||
app = FastAPI(
|
||||
title="Hub Core Runtime",
|
||||
version=__version__,
|
||||
description="HelixForge hub framework and named-port runtime.",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
app.state.settings = resolved_settings
|
||||
app.state.port_store = resolved_store
|
||||
app.state.compat_store = (
|
||||
SQLCompatibilityStore(resolved_store)
|
||||
if resolved_store.backend_name == "postgresql"
|
||||
else None
|
||||
)
|
||||
app.state.contract_validator = ContractValidator()
|
||||
|
||||
@app.get("/healthz", response_model=HealthResponse, tags=["system"])
|
||||
async def healthz() -> HealthResponse:
|
||||
return HealthResponse(version=__version__)
|
||||
return HealthResponse(
|
||||
service="core-hub" if resolved_settings.legacy_health else "hub-core",
|
||||
version=__version__,
|
||||
)
|
||||
|
||||
@app.get("/readyz", response_model=ReadinessResponse, tags=["system"])
|
||||
async def readyz(response: Response) -> ReadinessResponse:
|
||||
ready = resolved_settings.is_ready(resolved_store.backend_name)
|
||||
dependency_checks = await resolved_store.readiness_checks()
|
||||
ready = resolved_settings.is_ready(resolved_store.backend_name) and all(
|
||||
value in {"ok", "not_applicable"} for value in dependency_checks.values()
|
||||
)
|
||||
if not ready:
|
||||
response.status_code = status.HTTP_503_SERVICE_UNAVAILABLE
|
||||
return ReadinessResponse(
|
||||
status="ok" if ready else "degraded",
|
||||
checks=resolved_settings.readiness_checks(resolved_store.backend_name),
|
||||
checks={
|
||||
**resolved_settings.readiness_checks(resolved_store.backend_name),
|
||||
**dependency_checks,
|
||||
},
|
||||
)
|
||||
|
||||
app.include_router(create_ports_router())
|
||||
app.include_router(create_compatibility_router())
|
||||
return app
|
||||
|
||||
|
||||
def _create_store(settings: RuntimeSettings) -> PortStore:
|
||||
if settings.backend == "memory":
|
||||
return InMemoryPortStore()
|
||||
if settings.backend == "postgresql":
|
||||
if not settings.database_url:
|
||||
raise RuntimeError("HUB_CORE_DATABASE_URL is required for PostgreSQL backend")
|
||||
from hub_core.runtime.postgres_store import PostgresPortStore
|
||||
|
||||
return PostgresPortStore.from_url(settings.database_url)
|
||||
raise RuntimeError(f"Unsupported HUB_CORE_BACKEND '{settings.backend}'")
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue