协作者的 presence 是短暂且非权威的,若无心跳则会过期,并通过带版本的会话令牌重新连接,因此编辑权限绝不会仅由过时的 presence 决定。
包状态: AI 辅助参考包。静态包验证已通过;实现场景尚未运行,需人工领域审核后方可稳定采用。
决策
Presence 表示谁似乎正在查看或编辑某个界面;它不是权限证明,也不是持久的文档状态。每个 presence 会话会以短间隔发送心跳;缺失心跳会自动使条目过期。重新连接时会获得带递增版本的新会话令牌,因此旧连接的延迟数据包无法恢复过时的头像。编辑锁或操作变换仍然是写入权限的权威;presence 仅用于通知 UI 交互。
范围
- Presence 的加入、心跳、离开、过期及重新连接握手。
- 仅对加入和离开事件进行有限审计;心跳不记录审计日志。
- 会话令牌版本生成及过时数据包丢弃规则。
- 向文档或房间频道的订阅者分发 presence 更新。
- 每用户及每文档的并发 presence 条目限制。
- 重新连接率、阻止幽灵会话数及心跳延迟的指标。
不包含内容
- 文档编辑的授权。
- 完整的 CRDT 或 OT 合并算法。
- 跨产品的持久用户状态。
合约
- 当心跳停止超过配置的 TTL,presence 条目即过期;无需手动清理保证正确性。
- 重新连接必须递增会话版本;旧版本消息会被丢弃,不影响显示状态。
- presence 丢失不会撤销写入令牌或意味着保存完成。
- 加入时需明确文档或房间 ID;全局 presence 流不能泄露无关资源。
- 强制每用户每文档最大并发会话数;超出时驱逐最旧的短暂会话。
- 服务器时间驱动过期;客户端时间可能偏差但不能延长 TTL 超过服务器确认。
- 未发送离开消息的断开连接仍会在 TTL 内过期。
- 加入和离开事件发出有限审计日志,包含 document_id、session_id、generation 及哈希后的 actor id;审计排除心跳噪声及直接的个人身份信息如邮箱或 IP。
实现指导
- presence 存储于内存或短 TTL 存储,不存入主文档表。
- 对大房间的更新分发做防抖处理,减少噪音同时满足 UX 延迟预算。
- 在 websocket 帧中包含版本号,简化客户端丢弃逻辑。
失败处理与防护措施
- 若 presence 服务分区,优先显示较少头像而非幽灵。
- 除非产品策略明确范围和同意,不在 presence 负载中暴露精确地理位置。
- 对重新连接引发的加入风暴进行速率限制。
验证与运维
- 监控过期会话数、过时数据包丢弃、重新连接成功率及心跳 99 百分位延迟。
- 通过混沌测试重启代理,验证幽灵会话在 TTL 内消失。
- 在目标仓库执行验收场景;打包场景不作为执行证据。
采用假设
- 夹具中的 TTL 和版本规则为配置选项。
- 团队将传输层(WebSocket/SSE)映射到相同语义合约。