跳转到内容

新增 IM 适配器

Gateway 负责平台接入、授权和转发,Chord 负责会话、执行与结果保存。收件有界且只在进程内有效;投递契约明确允许 Gateway 重启边界上的丢失或重复。

适配器实现身份核验、连接生命周期、事件归一化和发送。复用 IngressNormalizer 的有界异步工作、公共接纳与分发层的授权和回执,以及 IMTextSender 的分段、期限和发送诊断。新增平台不再新建收件库、去重数据库、迁移、命令路由器或恢复队列。

internal/im/im_adapter_host.go 提供账号、轮询和 Socket 的宿主接口,Telegram 与 Slack 已使用这些边界。优先依赖所需的小接口,不直接访问 NotificationRouter 内部状态。旧适配器仍有具体 router 依赖,在修改相关路径时逐步收口,不复制到新平台。平台事件 ID 与经过验证的账号、聊天身份进入统一 IngressEnvelope。ACK 时序由适配器负责:提交归一化不等于接纳,接纳不等于 Chord 执行完成。

只有额外本地前置条件才实现可选 readiness 接口,例如微信回复上下文。检查不得执行 I/O,通知必须在锁外调用。独立可用的 HTTP 发送不应仅因其他平台这样做就增加 WebSocket 就绪门控。实现 IMTextMetricsProvider 时增加编译期断言。

共享 UTF-16 计量、退避抖动等不含平台策略的小函数。重连、认证、心跳和限流规则保留平台语义。SDK 生命周期满足要求时优先复用;需要 fork 时必须有具体缺陷、固定来源、许可证、有限改动面和回归测试。Discord fork 复用上游协议类型,只保留所需生命周期与限流实现;依赖升级仍需与上游对照。

解析、身份和文本转换使用表驱动测试,可逐步加 t.Parallel()。授权、顺序、容量和回执在公共层完整测试;每个平台用少量集成测试证明正确接入公共层。使用假的 HTTP/WebSocket 对端验证协议和取消,无需真实凭据。

内部时序优先用 channel 与 testing/synctest。真实网络、进程测试仍需期限,但先等待实际事件再断言。清理 fixture 前等待 worker 退出。根包 TestMain 隔离每个测试进程的机器级锁;同进程并行用例仍需不同账号,除非专门测试争用。修改环境或包级全局变量的用例保持串行。

分别运行以下门禁:

Terminal window
./scripts/check-go-quality.sh
# 包含覆盖率、格式、vet 与 staticcheck。
go test -race -short -timeout=5m ./...
CHORD_GATEWAY_CONTRACT_CHORD_REPO=/path/to/chord ./scripts/check-chord-contract.sh

CI 将单测覆盖率、race 和跨仓库契约分成独立 job。契约门禁要求可构建的 Chord checkout,缺失时不得静默跳过。同一测试进程对同一源码目录只构建一次 Chord CLI 并共享只读文件;测试期间不能修改其源码或构建环境。

分别统计适配器生产代码、公共代码、测试与复制的依赖代码。首版纯文本适配器应主要做事件归一化和传输操作;如果又新增数千行公共设施,应重新评审设计,不能只凭测试通过接受。这是审查信号,不是硬性行数限额。

先交付文本命令与回复。卡片、附件、可编辑流式预览、多企业安装作为独立能力,按具体需求和测试逐项增加。新增平台通常只需修改其适配器、工厂/配置注册和双语文档;反复改动公共调度说明边界尚未收好。跨重启等更强保证必须作为产品决策,不能在接入平台时附带引入。