From 8424af5343422cafb81eb888019631c39d212671 Mon Sep 17 00:00:00 2001 From: ogt Date: Sat, 11 Jul 2026 20:12:02 +0800 Subject: [PATCH] fix(worker): delegate production ddl to cd --- apps/api/src/core/config.py | 7 +++++ apps/api/src/workers/signal_worker.py | 29 +++++++++++++------ .../tests/test_runtime_bootstrap_guards.py | 21 ++++++++++++++ k8s/awoooi-prod/08-deployment-worker.yaml | 2 ++ 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/apps/api/src/core/config.py b/apps/api/src/core/config.py index be547c346..71926624a 100644 --- a/apps/api/src/core/config.py +++ b/apps/api/src/core/config.py @@ -298,6 +298,13 @@ class Settings(BaseSettings): "processes that share a constrained production role." ), ) + DATABASE_BOOTSTRAP_DDL_ENABLED: bool = Field( + default=True, + description=( + "Run idempotent schema bootstrap DDL during process startup. " + "Production workers disable this after CD migration preflight." + ), + ) # ========================================================================== # Redis (192.168.0.188:6380, DB 0 - 與 OpenClaw 共用) diff --git a/apps/api/src/workers/signal_worker.py b/apps/api/src/workers/signal_worker.py index f070ca0cb..f6846e7bf 100644 --- a/apps/api/src/workers/signal_worker.py +++ b/apps/api/src/workers/signal_worker.py @@ -582,15 +582,26 @@ async def _main() -> None: await init_redis_pool() await init_worker_redis_pool() # Worker 專屬,無超時限制 - # Initialize PostgreSQL (Episodic Memory) - 確保 incidents 表存在 - try: - await init_db() - logger.info("postgresql_initialized", status="ok") - except Exception as e: - logger.error( - "postgresql_init_failed", - error=str(e), - message="Episodic Memory (DB) will be unavailable - incidents won't persist", + # Production schema ownership belongs to CD migration/preflight. Local and + # development workers retain the idempotent bootstrap fallback by default. + if settings.DATABASE_BOOTSTRAP_DDL_ENABLED: + try: + await init_db() + logger.info("postgresql_initialized", status="ok") + except Exception as e: + logger.error( + "postgresql_init_failed", + error=str(e), + message=( + "Episodic Memory (DB) will be unavailable - incidents " + "won't persist" + ), + ) + else: + logger.info( + "database_bootstrap_ddl_skipped", + owner="cd_migration_preflight", + workload="signal_worker", ) try: diff --git a/apps/api/tests/test_runtime_bootstrap_guards.py b/apps/api/tests/test_runtime_bootstrap_guards.py index 1c640e466..2e5d7ab7f 100644 --- a/apps/api/tests/test_runtime_bootstrap_guards.py +++ b/apps/api/tests/test_runtime_bootstrap_guards.py @@ -8,10 +8,13 @@ Runtime bootstrap guard tests. from __future__ import annotations +import inspect from collections.abc import Awaitable +from pathlib import Path from typing import Any import pytest +import yaml from sqlalchemy.exc import DBAPIError @@ -63,6 +66,24 @@ class _ConnectionBudgetEngine: raise RuntimeError('too many connections for role "awoooi"') +def test_production_worker_delegates_bootstrap_ddl_to_cd() -> None: + from src.workers import signal_worker + + root = Path(__file__).resolve().parents[3] + manifest = yaml.safe_load( + (root / "k8s/awoooi-prod/08-deployment-worker.yaml").read_text( + encoding="utf-8" + ) + ) + container = manifest["spec"]["template"]["spec"]["containers"][0] + env = {item["name"]: item.get("value") for item in container["env"]} + source = inspect.getsource(signal_worker._main) + + assert env["DATABASE_BOOTSTRAP_DDL_ENABLED"] == "false" + assert "if settings.DATABASE_BOOTSTRAP_DDL_ENABLED" in source + assert 'owner="cd_migration_preflight"' in source + + def test_get_engine_uses_database_pool_budget(monkeypatch): from src.db import base as db_base diff --git a/k8s/awoooi-prod/08-deployment-worker.yaml b/k8s/awoooi-prod/08-deployment-worker.yaml index 8d9162f6f..52fe58bc8 100644 --- a/k8s/awoooi-prod/08-deployment-worker.yaml +++ b/k8s/awoooi-prod/08-deployment-worker.yaml @@ -167,6 +167,8 @@ spec: value: "0" - name: DATABASE_NULL_POOL value: "true" + - name: DATABASE_BOOTSTRAP_DDL_ENABLED + value: "false" - name: AWOOOI_BUILD_COMMIT_SHA value: "ea857399517abed2824e536a2dda7e77463512c3" - name: ENABLE_AWOOOP_ANSIBLE_CANDIDATE_BACKFILL_WORKER