fix(api): delegate production bootstrap ddl
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m42s
CD Pipeline / build-and-deploy (push) Failing after 11m22s
CD Pipeline / post-deploy-checks (push) Has been skipped

This commit is contained in:
ogt
2026-07-14 16:23:30 +08:00
parent 3933b0f397
commit b10a7d150a
7 changed files with 608 additions and 12 deletions

View File

@@ -155,6 +155,25 @@ def _close_unscheduled_coroutine(coro: Coroutine[Any, Any, Any]) -> None:
logger.warning("api_background_task_close_failed", error=str(exc))
async def initialize_api_database() -> bool:
"""Run local/dev bootstrap DDL or emit the production ownership receipt."""
if not settings.DATABASE_BOOTSTRAP_DDL_ENABLED:
logger.info(
"database_bootstrap_ddl_skipped",
owner="cd_migration_preflight",
workload="api",
reason="database_bootstrap_ddl_disabled",
)
return False
await init_db()
db_url = settings.DATABASE_URL
logger.info(
"database_initialized", url=db_url.split("@")[-1] if "@" in db_url else db_url
)
return True
def _resolve_request_project_context(request: Request) -> tuple[str | None, str]:
"""Resolve tenant context for RLS while keeping non-webhook routes fail-closed."""
for candidate in (
@@ -293,12 +312,9 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]:
return None
return asyncio.create_task(coro, name=task_name)
# CTO-201: Initialize PostgreSQL database (統帥鐵律: 禁止 SQLite)
await init_db()
db_url = settings.DATABASE_URL
logger.info(
"database_initialized", url=db_url.split("@")[-1] if "@" in db_url else db_url
)
# CTO-201: production DDL belongs to CD migration preflight; local/dev keeps
# the default bootstrap path (統帥鐵律: 禁止 SQLite).
await initialize_api_database()
# Phase 5: Initialize HTTP Clients (ClickHouse, Ollama)
# 統帥鐵律: 連線池在啟動時建立,關閉時回收