refactor: config_views 单入口 + 0语义统一 + FakeAI 收敛(清理单#1#2#3)
- #3 六个消费视图 resolver 收拢 app/platform/config_views(单一定义点): resolve_email/push/ai_settings ← 各服务文件, resolve_contact_flags/ context_seed_map ← conversation, name_to_region_extras ← manager __init__ 内联取值(or None 语义原样)——函数体逐字搬入,服务层 import 之, 旧定义删;Phase 3 编辑器/试金石与该模块对接 - #2 限流 0 语义统一: conn_limiter.try_acquire 的 limit 与 chat_rest 的 rate_limit_per_hour 取值同款——0 或负 = 回退出厂默认(与姊妹键一致), 原 conn_limiter 0=全拒改为回退;chat_rest 取值抽 _resolve_rate_limit 纯函数供锚定 - #1 FakeAI 收敛进 conftest(超集: extract/evaluate/eval_calls),四份拷贝 删(test_lead_email_trigger/test_cc_integration/test_channel_hygiene/ test_lead_push_wiring——计划记三份,grep 实有四份;push_wiring 经 evaluate 参数注入原本地固定返回值,断言零改动) 全量 558 passed(554 + 新增 4: 单入口/内联等价/两处 0 语义) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -23,48 +23,21 @@ import httpx
|
||||
from sqlalchemy import func, select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.engine.config import settings
|
||||
# env settings 单例引用: Task 10 起 resolver 消费移至 config_views,本模块
|
||||
# 不再直读 settings——保留 import 供测试 monkeypatch 锚点(svc.settings.PUSH_*
|
||||
# 20+ 处;settings 是单例对象,经任一模块引用 patch 均全局生效)
|
||||
from app.engine.config import settings # noqa: F401
|
||||
from app.engine.models import (
|
||||
Conversation, CustomerProfile, Evaluation, IntentLevel, LeadPushLog,
|
||||
Message, MessageRole,
|
||||
)
|
||||
from app.engine.services.cc_completion import cc_state_for, completion_note, outbound_e164
|
||||
from app.engine.services.ip_service import resolve_country
|
||||
# Task 10: 推送参数 resolver 收拢至 config_views(单一定义点)
|
||||
from app.platform.config_views import resolve_push_settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def resolve_push_settings(config_data: dict | None) -> dict:
|
||||
"""租户 config.push → 推送参数(Task 9 接线; env settings 回退)。
|
||||
|
||||
空槽回退哨兵(审查 Important-1, 与 ai.model 同款纪律):
|
||||
- 布尔/字符串: falsy 出厂默认(False/空串)视同"未设置"→ 回退 env
|
||||
PUSH_*——部署级 .env 开关是平台默认集的一部分,租户未配置时继承,
|
||||
不静默关停;
|
||||
- 数值字段(timeout/max_attempts/retry_backoff_base): 出厂 None =
|
||||
"未设置"→ 回退 env(settings 自带默认 10.0/3/1.0,最终行为与出厂
|
||||
truthy 默认时一致),租户显式数值(含显式 0)优先于 env。
|
||||
config_data=None 路径仅供测试直调,生产调用一律传 runtime.config.data。
|
||||
已知边界: env 开 + 租户显式 false 无法区分于未配置(布尔空槽只有
|
||||
False),Phase 2 admin 落地时以"平台清 env、配置显式写 false"解决。
|
||||
"""
|
||||
p = ((config_data or {}).get("push")) or {}
|
||||
return {
|
||||
"enabled": bool(p.get("enabled") or settings.PUSH_ENABLED),
|
||||
"url": p.get("url") or settings.PUSH_API_URL,
|
||||
"api_key": p.get("api_key") or settings.PUSH_API_KEY,
|
||||
"prefix": p.get("prefix") or settings.PUSH_EXTERNAL_KEY_PREFIX,
|
||||
# 数值哨兵: None(出厂/显式清空)→ env;显式数值优先
|
||||
"timeout": (p.get("timeout") if p.get("timeout") is not None
|
||||
else settings.PUSH_TIMEOUT_SECONDS),
|
||||
"max_attempts": (p.get("max_attempts")
|
||||
if p.get("max_attempts") is not None
|
||||
else settings.PUSH_MAX_ATTEMPTS),
|
||||
"retry_backoff_base": (p.get("retry_backoff_base")
|
||||
if p.get("retry_backoff_base") is not None
|
||||
else settings.PUSH_RETRY_BACKOFF_BASE),
|
||||
}
|
||||
|
||||
# 对方契约(docs/AI_INQUIRY_PUSH_API.md): phone/whatsapp/email 至少一个有效
|
||||
_TRIO = ("phone", "whatsapp", "email")
|
||||
_CST = timezone(timedelta(hours=8))
|
||||
|
||||
Reference in New Issue
Block a user