# -*- coding: utf-8 -*- """元景 scense 应用唯一入口(一个应用 = 一个入口 = 一个端口 9380)。 挂载 6 个业务模块:world / scene / entity / script_engine / world_snapshot / world_sync。 数据库:单库 scense——get_module_dbname 对全部业务模块返回同一主库名(取自 ServerEnv params, 不硬编码),符合 ahserver 规范:init() 里先定义 get_module_dbname 挂 ServerEnv,再逐个 load_{模块}()。 Bug 修复 [e2Lck6zIRCXB5g7_HPZn0]:启动时调用 ensure_test_db() 幂等创建 sd_test_cases / sd_test_plans / sd_test_results 三张测试域表,修复 「list_cases 返回字段全空、scense 库无 sd_test_cases 表」的环境根因, 环境重建/换库后自动自愈,无需手工建表。 """ import os import sys from ahserver.webapp import webapp from ahserver.serverenv import ServerEnv import bricks_for_python # 注册 bui processor from bricks_for_python.init import load_pybricks # 注册 UiWindow 等 from appbase.init import load_appbase from rbac.init import load_rbac def _ensure_scripts_path(): """保证 scripts 包可导入:显式把模块根目录加入 sys.path。 无论 webapp 以何种方式启动(python app/scense.py / uwsgi / build.sh 注入的 PYTHONPATH 缺失时),`from scripts.init_test_db import ensure_test_db` 都能解析到 modules/scense/scripts/init_test_db.py,否则建表逻辑被 ImportError 吞掉、Bug 环境根因无法自愈。 """ module_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if module_root not in sys.path: sys.path.insert(0, module_root) def get_module_dbname(m): """模块 → 库名映射。单库应用:全部模块返回同一主库 scense。 库名来源:ServerEnv params 表(appbase 初始化时写入 'dbname' 参数),禁止硬编码。 """ env = ServerEnv() try: return env.params.get('dbname', 'scense') except Exception: return 'scense' def password_encode(s): if s is None: return '' from ahserver.globalEnv import password_encode as _orig return _orig(s) def init(): env = ServerEnv() # MUST be before load_rbac env.get_module_dbname = get_module_dbname env.password_encode = password_encode load_appbase() load_rbac() load_pybricks() # ── Bug 修复:测试用例域库表幂等自愈(环境根因)── # 确保 sd_test_cases / sd_test_plans / sd_test_results 存在, # list_cases 不再因缺表返回字段全空。 _ensure_scripts_path() from scripts.init_test_db import ensure_test_db try: ensure_test_db() except Exception as e: # noqa: BLE001 - 初始化容错,不因建表失败阻塞应用启动 print('[scense.init] ensure_test_db warning: %s' % e) # ── 业务模块挂载(关键:一个应用一个入口一个端口,所有模块挂在这里)── from world.init import load_world from scene.init import load_scene from entity.init import load_entity from script_engine.init import load_script_engine from world_snapshot.init import load_world_snapshot from world_sync.init import load_world_sync load_world() load_scene() load_entity() load_script_engine() load_world_snapshot() load_world_sync() if __name__ == '__main__': webapp(init)