Repository navigation
fix(mac): 复用连接认证以停止后台内存增长 - #12
Conversation
- 由连接池统一持有 Keychain 认证,后台传递凭据引用 - 保存和重新授权时更新认证,并保留锁定、删项与多连接恢复 - 覆盖真实 Keychain 回归,将本机构建更新到 build 20
xiaoland
left a comment
There was a problem hiding this comment.
已完成对当前 head 395800e 的功能与实现审查。解决重复读取 file-based Keychain 凭据导致长期运行内存增长的方向合理:由 PeerDatabase 管理认证复用,Capture / LocalFiles 只传递凭据来源,不要求推翻该方案。
合并前建议修复以下两处行为问题(详见行内评论):
- 首次 Capture 在实际验证 Keychain 凭据前已 markDispatch,失败时会虚增 attempts 并进入“可能已发送”的恢复语义。
- 对同一 target 混用
.keychain(store)与.password(...)时,池复用会覆盖此前的认证来源,导致续租可以绕过声明的 Keychain 锁定/删除检查。
请优先用针对性的回归测试验证原有行为与跨入口授权约束。暂不建议在此次 hotfix 内增加通用凭据框架或扩大重构范围。
补充设计审查:先确认认证会话语义,再决定需要多少技术机制这次内存增长可能暴露了凭据生命周期与业务调用生命周期混淆:后台续租和 LocalFiles 刷新都约每 30 秒执行,旧实现反复向 file-based Keychain 取密;PR 所述每次约 16 KiB、六天约 521 MiB 的数量级与这些周期性调用相符(仅为归因线索,不等于严格证明)。既有 PostgresClient 已持有认证配置,业务操作不应反复取密。让连接池拥有认证会话是正确方向。 但新方案又引入了每次访问的 Keychain revision/锁定/删项检查、全属性序列化、进程级 generation 协调等。这些机制究竟由哪条产品需求驱动,还是为了满足未经充分论证的技术约束? 希望本 PR 先回到产品语义,而不是继续叠加兼容和状态机制。 建议首先区分:
我倾向的简化目标是:Keychain 用于持久化和必要时取得认证材料;PeerDatabase 持有已授权会话;正常会话中的普通数据库操作不再访问 Keychain;应用内主动改密或显式撤销时确定性失效;真正需要重新取密且失败时才提示处理。 若确实希望“锁定 Keychain 即停止已有后台会话”,请给出用户场景,再保留对应检查。 请在本 PR 内结合上述语义重新审视实现和验收,优先删除不必要的约束与代码,而不是扩大抽象。保留内存修复已有证据,并验证:长时间后台操作不重复取密/内存不线性增长、主动改密正确生效、后台不弹授权窗口、Capture 状态不虚增,更新 README 与测试。 备注:之前关于 password/keychain 混用绕过锁定检查的行内 P2,是以现有 PR 将持续锁定检查视为既定要求为前提指出的内部不一致。若产品语义最终简化为会话授权,应相应调整该评论的验收目标,而不是为满足旧约束继续堆积技术逻辑。 |
xiaoland
left a comment
There was a problem hiding this comment.
补充两处与 PR Conversation 中的产品语义审查直接相关的实现锚点。这里要求先核对必要性,再决定删减方案;不要求为本 hotfix 新增架构。
- 移除普通操作的 Keychain revision 检查与全局 generation - 通过共享 HostContext 明确更新和撤销数据库认证会话 - 首次 Capture 在标记发送前准备认证,失败保留零次尝试 - 补充旧引用、重新授权及 Capture 恢复回归,更新 build 21
目的与行为
Mac 后台续租、目录刷新与 Capture 重试曾反复向 file-based Keychain 取密码。本机合成凭据对照复现每次成功取密约增加 16 KiB;原进程连续运行六天后 footprint 约 581 MB,其中约 528 MB 为匿名 VM。
认证现在归
PeerDatabase的已授权会话所有。没有会话时取得一次凭据;普通查询、重试和续租直接复用 client,不再查询 Keychain、序列化属性或协调全局 generation。.password与.keychain只提供冷启动凭据;明确的authorize/invalidate更新或撤销会话,旧引用不能回切密码、用户名或 TLS 配置。Host、Capture 与 Local Files 共用一个
PeerHostContext。连接编辑和 Capture 待办改密都通过该 owner 更新认证;留空密码保存连接会重新读取 Keychain,失败则结束该会话。Keychain 外部锁定、删项或修改不会自动撤销既有数据库会话。首次 Capture 先准备认证,再持久化可能发送的状态。凭据不可用时保持
attempts == 0,保留原 UUID、材料和目标;取消文案仍为“尚未发送”,恢复认证后才真正增加尝试次数。范围:Mac App、PeerCore、随包 Capture 与 Local Files;本机候选为 0.1.0 build 21。
审查处理
markDispatch前,覆盖失败、取消、停止和重试。保留现有 file-based Keychain,以继续读取已安装应用的凭据。本次问题由不必要的重复取密触发,不把更换持久化位置设为修复前置。Data Protection Keychain 有不同的访问控制和宿主签名要求,迁移需单独安排。Apple TN3137
验证
bash scripts/check.sh通过:70 项测试中 66 项执行通过,4 项数据库依赖场景按原环境条件跳过;格式、lint 和脚本检查通过。SWIFT_JOBS=2 bash scripts/check-core.sh通过:独立消费者仅链接 Core,不启动 App/UI。45e5669的 CI 全部通过;签名 universal 构建通过,arm64/x86_64 双架构与签名验证通过,指定要求与原开发包一致。风险、回退与交付
采用数据库会话授权;Keychain 的锁定或删项只影响下一次取密。需要强制核验时,可重新保存连接或重启应用。README、Core README 与 Local Files README 已同步。
沿用现有 Bundle ID 和开发证书,本机配置、材料与数据库 schema 不迁移;原路径旁保留
.InKCre-before-build21.app供回退。签名应用、DMG、dSYM、脚本与验证记录保存在本机候选制品mac-keychain-memory-build21-45e5669。没有父/子堆叠 PR。实现、构建、安装与 CI 已完成,待复核 Capture 状态边界与会话语义。图形交互验收受上述本机显示环境限制。