feat: derive the schema mode from the telemetry backend
This commit is contained in:
@@ -331,6 +331,61 @@ class TestAssemblyGuards:
|
||||
assert GatewaySettings.from_env("LLM", env=env_ok).backpressure.stall_window_s == 60.0
|
||||
|
||||
|
||||
class TestTelemetrySchemaMode:
|
||||
"""PGW_TELEMETRY_SCHEMA_MODE 三态(issue #13 设计 §4.1)。
|
||||
|
||||
键未设时按后端**不对称**派生: SQLite 是下游自己的本地文件(没有 DBA、
|
||||
没有迁移工具、没有第二个系统碰它),补列是毫秒级元数据操作,故默认 auto;
|
||||
PG 是共享生产表,ALTER 取 ACCESS EXCLUSIVE 锁会阻塞该表其后的所有查询,
|
||||
而遥测是业务路径上的内联 await,故默认 manual。显式设置两侧都可覆盖——
|
||||
"可覆盖"正是三态相对两态多出来的那一态,派生本身盖不住它。
|
||||
"""
|
||||
|
||||
def _sqlite_env(self, **overrides):
|
||||
return _env(
|
||||
PGW_TELEMETRY_BACKEND="sqlite",
|
||||
PGW_TELEMETRY_SQLITE_PATH="logs/telemetry.db",
|
||||
**overrides,
|
||||
)
|
||||
|
||||
def _pg_env(self, **overrides):
|
||||
return _env(
|
||||
PGW_TELEMETRY_BACKEND="postgres",
|
||||
PGW_TELEMETRY_PG_DSN="postgresql://u:p@h:5432/polygateway",
|
||||
**overrides,
|
||||
)
|
||||
|
||||
def test_unset_key_derives_auto_for_sqlite(self):
|
||||
s = GatewaySettings.from_env("LLM", env=self._sqlite_env())
|
||||
assert s.telemetry_auto_migrate is True
|
||||
|
||||
def test_unset_key_derives_manual_for_postgres(self):
|
||||
s = GatewaySettings.from_env("LLM", env=self._pg_env())
|
||||
assert s.telemetry_auto_migrate is False
|
||||
|
||||
def test_unset_key_derives_manual_for_none_backend(self):
|
||||
"""backend=none 无 recorder 消费该字段,派生结果必须是 False 而非 sqlite 那档。"""
|
||||
s = GatewaySettings.from_env("LLM", env=_env())
|
||||
assert s.telemetry_auto_migrate is False
|
||||
|
||||
def test_explicit_manual_overrides_sqlite_default(self):
|
||||
s = GatewaySettings.from_env(
|
||||
"LLM", env=self._sqlite_env(PGW_TELEMETRY_SCHEMA_MODE="manual")
|
||||
)
|
||||
assert s.telemetry_auto_migrate is False
|
||||
|
||||
def test_explicit_auto_overrides_postgres_default(self):
|
||||
s = GatewaySettings.from_env("LLM", env=self._pg_env(PGW_TELEMETRY_SCHEMA_MODE="auto"))
|
||||
assert s.telemetry_auto_migrate is True
|
||||
|
||||
def test_invalid_mode_rejected_naming_the_env_key(self):
|
||||
"""报错须点出 env 键名: 这条路的调用方看得懂的是键名,不是字段名。"""
|
||||
with pytest.raises(ValueError, match="PGW_TELEMETRY_SCHEMA_MODE"):
|
||||
GatewaySettings.from_env(
|
||||
"LLM", env=self._sqlite_env(PGW_TELEMETRY_SCHEMA_MODE="enabled")
|
||||
)
|
||||
|
||||
|
||||
class TestOcrSettings:
|
||||
"""M3 OcrSettings(设计 §3.4): 复用 GatewaySettings,无 OCR 专用键。"""
|
||||
|
||||
@@ -555,6 +610,16 @@ class TestCrossFieldInvariants:
|
||||
with pytest.raises(ValueError, match="telemetry_pg_dsn"):
|
||||
dataclasses.replace(base, telemetry_backend="postgres")
|
||||
|
||||
def test_none_backend_forces_auto_migrate_off(self):
|
||||
"""backend=none 时没有 recorder 消费该字段,True 是自相矛盾的状态(issue #13)。
|
||||
|
||||
env 路的派生已给出 False,但直接构造与 dataclasses.replace 这两条同等
|
||||
官方的装配路仍能把 True 传进来——不变量归位到构造期,三条路才一致。
|
||||
"""
|
||||
base = self._base() # telemetry_backend="none"
|
||||
replaced = dataclasses.replace(base, telemetry_auto_migrate=True)
|
||||
assert replaced.telemetry_auto_migrate is False
|
||||
|
||||
# —— 标量域 ——
|
||||
|
||||
def test_negative_structured_retries_rejected(self):
|
||||
|
||||
Reference in New Issue
Block a user