Skip to content

@vent1000 三个状态问题:调查与修复

来源:社区反馈,2026-09-07 07:17:47 UTC。

修复基于生产代码 869d3427e,分支 codex/vent1000-state-fixes。本次处理打开聊天、签到提示、切换自有 API 三项;LongCat 上游 400 属于另一个问题。

个案复查:已确定的范围与尚缺的证据

用户质疑“为何只有他遇到”后重新核实。下文的竞态和布局测试证明了代码缺陷,不能单独证明它们就是这位用户三项反馈的全部原因。

  • 重新读取本人原帖:签到是在新标签页/刷新后反复提示;API 是聊天模型选择窗口确认后仍显示 Yumina 模型。旧 GET 覆盖刚领取状态的竞态,单独不足以解释每次新开页面都复发。
  • 2026-09-07 08:07–08:08 UTC,以该账号的已有有效会话做实际 GET 验证,身份核对通过:/api/check-ins/status 返回 dayKey=2026-09-07, checkedToday=true, claimable=false/api/subscription/status 返回 preferredProvider=official;涉事会话 GET 返回 29 条消息,最后一条仍为 ea290b37-52cf-4736-9619-8f2a21239d51。没有执行生产领取、模式切换或生成请求。
  • 这几项真实的登录后 200 响应均为 Cloudflare DYNAMIC、无 Age,同时没有 Cache-ControlExpiresLast-ModifiedETag。不能把它定性为已确认的 Cloudflare 缓存事故;但个人状态没有显式禁止缓存是需要补齐的边界。
  • 扩展 Railway 两个部署的同来源、同浏览器请求记录:07:02–07:54 可见多次资料/消息查询、领取 POST 和模式 PATCH,未见签到状态 GET 或余额状态 GET。这与部分读取在客户端/中间层未抵达源站相符,但日志筛选本身不能确定其浏览器本地返回了什么。/index.html 也是应用回到前台时的版本检查地址,不能将每个命中都算成一次完整刷新。
  • 故障请求的 user agent 为 Windows Firefox 155。不能仅凭浏览器版本判断责任,也不能证明只有这一位用户受影响。
  • 07:28:27、07:28:32 在首次反馈之后又出现两次资料 PATCH,因此后来数据库为 official 不能倒推 07:14 的首次切换未保存。原 HTTP 日志缺少 body,无法确认这两次的目标模式。
  • PostHog 前端事件仍缺失;服务端 server_request 仅采样正常请求的 1%,所以其事件缺席不能单独作为请求未到达的证据。

补充处理:服务端对签到、余额、本人资料、密钥/模型和个人会话接口明确返回 private/no-store,保留公开发现页缓存和消息流自己的 no-transform 策略;聊天初次读取和消息刷新也显式绕过 HTTP 缓存。新增“连续新开三次页面仍不能恢复旧签到/模式快照”的客户端回归及服务端缓存边界测试。这些是对旧状态路径的防护,不是对本人缓存已损坏的取证结论。

同时为保存模式和领取结果添加低频、明确的服务端事件 provider_preference_saved / check_in_claim_result,只记录目标/已保存模式或日期/是否领取,不记录密钥、资料或聊天内容。旧数据无法回溯补齐;上线后再次操作时可核实返回结果。

最后仍需要他原浏览器与同电脑无痕窗口的对照,或修复版本上的实际重试结果,才能确认个案闭环。已经向站点负责人请求该对照结果;没有代其发布社区回复。

打开聊天看不到最新消息

生产只读查询确认涉事会话有 29 条已保存消息,最后一条完整。低于服务端初次读取 200 条、客户端渲染 50 条的阈值,没有发现已存记录被分页截掉或丢失的证据。

在真实 MessageList 组件的 JSDOM 回归测试中模拟 iframe 初始高度为 0,稍后视口变成 500、消息内容高度变成 2000。原实现只在消息首次加载时滚动一次,后续布局变化后 scrollTop 仍为 0,测试失败。它能复现“消息都在,但没有定位到最新消息”的显示故障。

修复:在首次打开期间观察消息栈和视口尺寸,随布局变化定位到底部;用户滚轮、触摸、指针或键盘操作后停止。消息更新、读取更早历史、切换会话和卸载时释放观察器。访客预览不启用。滚动保护识别这一初始定位,避免把它误认成用户翻阅并阻止之后正常滚动。

验证包含延迟布局、内容变高、视口缩小、用户向上翻阅、键盘翻阅、切换会话、访客预览,以及既有历史分页回归。

签到一直提示可领取

生产当天的签到及账本均存在,03:26:54 UTC 已发放 100 Mushies。07:10:48 重复领取接口返回 200;该接口在已领取时返回 awarded:null,不会重复发放。

回归测试将签到状态 GET 延迟到领取 POST 成功后返回:原 store 会用旧的 claimable:true 覆盖刚收到的已领取状态,测试失败。

修复:领取时使旧 GET 响应失效,领取期间暂停状态读取,合并重复状态请求;状态 GET 使用 no-store。回到页面、重新打开余额弹窗时重新读取服务端状态,更新其他标签页领取后的提示。重复领取的 awarded:null 仍正常更新已领取状态。

确认切换自有 API 后仍显示官方模式

生产记录显示用户已有自有 API 配置,当天早些时候也成功使用过。报告前的 PATCH /api/users/me 返回 200,但日志没有请求/响应正文,无法确认当次写入的目标值或之后是否被其他操作改回。

代码缺陷可以稳定复现:原切换流程在 PATCH 成功后依靠额外的余额、资料查询更新界面;这两个查询吞掉错误,余额查询失败时聊天仍显示旧 provider。另一个测试发现:余额 store 虽对内存状态做了请求顺序检查,却在检查前写 localStorage,导致旧响应污染下次访问时的模式。

修复:三处切换入口共用保存函数,校验 PATCH 返回的 preferredProvider,并立即同步资料、聊天模式和持久化状态;切换不依赖额外余额查询。保存成功后旧的资料/余额响应失效,localStorage 也受同样顺序保护。非成功或目标值不符时保留错误提示。

验证与边界

  • 首轮回归在修改前失败,修改后通过;补充后客户端状态/布局/历史分页 18 项通过,服务端签到日期与缓存边界 22 项通过。
  • pnpm build 通过(5/5),pnpm typecheck 通过(8/8)。构建保留既有的大包及静态/动态混合导入提示。
  • 首轮完整前端测试:688 项,685 通过,3 失败。失败全部位于 mobile-nav-drawer-layout.test.ts;从生产基线导出该测试及其所有读取文件单独执行,也复现相同 3 个失败,属于已有菜单样式断言不一致。
  • 补充后的完整前端测试:689 项,686 通过,仍只有上述 3 项既有失败。补充后的构建(5/5)与类型检查(8/8)再次通过。
  • 调查和本地验证未修改生产数据,未执行真实浏览器验证。2026-09-07 用户已授权上线;发布时已合入最新主分支 7e742c3c0,前端相关回归扩展为 32 项通过,服务端相关回归 22 项通过。生产部署结果以发布记录为准。
  • PostHog 未提供故障时段的前端事件/回放,HTTP 日志没有响应正文,因此这些是与报告现象相符、已在本地复现并修复的代码缺陷;不能据此声称用户当时的每条交互链路均被完整还原。上线后仍需观察实际反馈。
  • 凭据未写入代码或报告;PostHog 使用此前已验证的本机加密凭据。