diff --git a/apps/api/src/core/config.py b/apps/api/src/core/config.py index e38c1d87..97b7f2c5 100644 --- a/apps/api/src/core/config.py +++ b/apps/api/src/core/config.py @@ -51,6 +51,21 @@ class Settings(BaseSettings): description="Enable mock mode for external services (Redis, Ollama, OpenClaw, PostgreSQL, SigNoz)", ) + # ========================================================================== + # Phase 16: leWOOOgo 積木化絞殺者模式 (Strangler Fig Pattern) + # 2026-03-26 統帥批准立即執行 + # + # 功能開關: + # - False: 使用 apps/api 內嵌版本 (當前) + # - True: 使用 lewooogo-brain/lewooogo-data 套件版本 + # + # 回滾指令: kubectl set env deployment/awoooi-api USE_NEW_ENGINE=false + # ========================================================================== + USE_NEW_ENGINE: bool = Field( + default=False, + description="Phase 16: True=lewooogo packages, False=內嵌版本", + ) + # ========================================================================== # CORS - 嚴格白名單 (無 UAT, 無 wildcard) # ========================================================================== diff --git a/apps/api/src/services/incident_memory.py b/apps/api/src/services/incident_memory.py index c0fdaa82..077f736f 100644 --- a/apps/api/src/services/incident_memory.py +++ b/apps/api/src/services/incident_memory.py @@ -2,6 +2,7 @@ Incident Memory Provider - 事件記憶體提供者 ============================================ Phase 6.4e: DualIncidentMemory 整合 +Phase 16 R1.2: 絞殺者模式 (Strangler Fig Pattern) 2026-03-26 設計: - 實作 IIncidentMemory 協定 (Protocol) @@ -13,8 +14,14 @@ Phase 6.4e: DualIncidentMemory 整合 - Episodic Memory (PostgreSQL): 永久 - 反向索引: 30 分鐘 TTL (聚合窗口) +Phase 16 絞殺者模式: +- USE_NEW_ENGINE=False: 使用此內嵌版本 (當前預設) +- USE_NEW_ENGINE=True: 使用 lewooogo-brain 套件版本 +- 回滾指令: kubectl set env deployment/awoooi-api USE_NEW_ENGINE=false +- 監控週期: 48 小時驗證期 + NOTE: 此模組為 lewooogo-brain/adapters/incident_memory.py 的 apps/api 內嵌版本 - 待 Phase 6.4i 完成 monorepo Docker 解法後,將直接引用 lewooogo-brain 套件 + Phase 16 R2 階段會在 48 小時驗證通過後移除此檔案 """ from datetime import UTC, datetime, timedelta @@ -469,15 +476,91 @@ class DualIncidentMemory: # ============================================================================= -# Singleton +# Singleton + 絞殺者模式 (Phase 16 R1.2) # ============================================================================= _dual_memory: DualIncidentMemory | None = None +_new_engine_memory: Any | None = None # lewooogo-brain 版本 def get_incident_memory() -> DualIncidentMemory: - """取得 DualIncidentMemory 實例 (Singleton)""" + """ + 取得 DualIncidentMemory 實例 (Singleton) + + Phase 16 絞殺者模式: + - USE_NEW_ENGINE=False (預設): 返回內嵌版本 + - USE_NEW_ENGINE=True: 返回 lewooogo-brain 套件版本 + + 回滾指令: kubectl set env deployment/awoooi-api USE_NEW_ENGINE=false + """ + from src.core.config import settings + + if settings.USE_NEW_ENGINE: + return _get_new_engine_memory() + else: + return _get_legacy_memory() + + +def _get_legacy_memory() -> DualIncidentMemory: + """取得內嵌版本 (Phase 16 舊引擎)""" global _dual_memory if _dual_memory is None: _dual_memory = DualIncidentMemory() + logger.info("incident_memory_initialized", engine="legacy_embedded") return _dual_memory + + +def _get_new_engine_memory() -> Any: + """ + 取得 lewooogo-brain 套件版本 (Phase 16 新引擎) + + 注意事項: + - 需要 lewooogo-brain 已安裝 (Dockerfile 已配置) + - PostgreSQL 整合尚未完成 (TODO in lewooogo-brain) + - 初次啟用建議 48 小時監控 + + 回滾: 設定 USE_NEW_ENGINE=false 即可瞬間切回 + """ + global _new_engine_memory + + if _new_engine_memory is None: + try: + # 延遲導入: 避免 lewooogo-brain 未安裝時啟動失敗 + from lewooogo_brain.adapters.incident_memory import ( + DualIncidentMemory as NewDualIncidentMemory, + ) + from src.core.redis_client import get_redis + from src.db.base import get_db_context + + redis_client = get_redis() + + # 初始化 lewooogo-brain 版本 + _new_engine_memory = NewDualIncidentMemory( + redis_client=redis_client, + pg_session_factory=get_db_context, + key_prefix="awoooi:incidents", + ) + + logger.info( + "incident_memory_initialized", + engine="lewooogo_brain_package", + redis_connected=True, + ) + + except ImportError as e: + # lewooogo-brain 未安裝,降級到內嵌版本 + logger.warning( + "lewooogo_brain_not_available_fallback_to_legacy", + error=str(e), + ) + return _get_legacy_memory() + + except Exception as e: + # 其他錯誤,降級到內嵌版本 + logger.error( + "new_engine_init_failed_fallback_to_legacy", + error=str(e), + ) + return _get_legacy_memory() + + return _new_engine_memory