修复泥点消耗刷新不及时 #138
Reference in New Issue
Block a user
Delete Branch "fix/one-mud-point-store"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
refactor:
fix:
修复旧请求覆盖问题
修复账号切换问题
主站原本已经每 4 秒轮询 external generation 任务状态, 在这里补充触发余额刷新的时机
WIP: 统一主站与AI游戏创作钱包状态to WIP: 修复泥点消耗刷新不及时发现 4 个需要修复的问题:
另外请修复当前 4 个 Prettier 失败文件,并整理 581323b4、658ebef5 两个空提交正文。修复后请基于新 head 重新跑四组 CI 并请求复审。
@@ -0,0 +72,4 @@return;}invalidateActiveRefresh();这里把
settledRefreshVersion直接推进到当前最新版本,同时上一步中止 active refresh。loadRechargeCenter()的普通 GET 快照可能早于之后发生的生成扣费或失败退款;它晚返回时会覆盖余额并吞掉终态刷新。我已复现:应用旧快照 80 后,即使被中止的刷新随后返回 100,Store 最终仍停在 80。请给快照绑定请求发起时的版本和 owner,只结算不晚于它的 invalidation,或让普通读统一走 Store,不能取消更晚的刷新。@@ -419,3 +434,3 @@useEffect(() => {if (!activeExternalTaskIds.length) {if (!walletActiveExternalTaskKey) {walletActiveExternalTaskKey初始为空时这里直接不启动轮询;首轮Promise.all任一列表请求失败只会清空任务,没有重试或已知 active ID。这样页面打开时的一次瞬时失败,就会令后续预扣和终态退款都没有钱包通知。请让 bootstrap 失败也有有界重试,或让轮询启动不依赖首次成功取得任务 ID。@@ -342,3 +373,1 @@profileCenter.rechargeCenter?.mudPointBalance?.totalPoints ??profileCenter.rechargeCenter?.walletBalance ??null;const balance = mudPointBalance?.totalPoints ?? null;这里移除了
rechargeCenter.walletBalance的兼容兜底,但账单 modal 仍传入fallbackBalance={balance ?? 0}。当响应只有 legacywalletBalance = 37、没有mudPointBalance时,充值弹窗显示 37,空账单却显示 0。请保留 owner 匹配的 legacy fallback,或显式展示不可用,不能伪造 0。@@ -641,3 +736,3 @@if (paymentChannel === WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_CHANNEL) {pendingWechatRechargeOrderIdRef.current = response.order.orderId;applyRechargeCenter(response.center);if (!applyRechargeCenter(response.center, true)) {owner 检查发生在
pendingWechatRechargeOrderIdRef.current = response.order.orderId之后,而且后续catch/finally也没有校验账号 revision。A 切换到 B 后,A 的延迟响应仍可覆盖或清空 B 的 pending order、二维码和提交状态;特殊错误路径还可能通过clearStoredAccessToken()清掉 B 的登录。请把一次充值从下单到确认的所有 ref、state 和认证副作用绑定同一个 owner + lifecycle revision,并在每次副作用前校验。复审后,上一轮 4 个功能问题已有对应修复,但仍有两个当前 head 的阻断:
请补齐 AbortSignal / 生命周期门禁及回归测试后重新请求复审。另请处理剩余 Prettier 失败文件与空提交正文。
@@ -383,0 +407,4 @@),);}).catch(() => {Promise.all 任一分支先失败时会进入 retry,但没有 abort 同一轮 controller;另一个列表请求若一直 pending,下一轮会覆盖 controller 引用,卸载时只能 abort 最新请求。请在安排 retry 前中止当前 attempt,或保存并清理全部 attempt controller;补“一侧 reject、另一侧 pending、重试后卸载”的测试,确保不会留下悬挂请求。
@@ -212,5 +212,5 @@await waitWechatPayConfirmDelay(delayMs);latestResponse = await confirmWechatPlatformProfileRechargeOrder(orderId);if (isWechatRechargeOrderTerminalForConfirmation(latestResponse.order)) {return latestResponse;这两个确认 helper 的每一次重试都在等待后直接调用 confirm API,没有 AbortSignal 或账号 revision 检查。A 的第一次确认返回 pending 后切换到 B,800ms 后这里仍会用当前全局 token 发 A 的第二次确认请求;apiClient 每次请求都即时读取 token,401 还可能 refresh/清掉 B 的登录。请让整个确认链持有 owner 生命周期的 AbortController,在每次 delay、confirm 和 watch 前检查/传递 signal,并在账号切换时中止;补 fake-timer 用例证明切换后不会产生第二个确认请求。
3cf10af96fto532df4d231处理空提交正文。
82826efa20to0397866d84复审确认 review 132 的两条功能阻断已经修复,支付确认链与任务 bootstrap 请求都具备对应取消和回归测试。
当前仍需处理:
decision-log.md的既有 Seedance 数量约束被格式化为0~~9 / 0~~3,改变了 Markdown 语义。ImageCanvasStageView.tsx、usePlatformProfileCenterController.ts失败。定向 116 项测试和四组 CI 当前全绿,提交正文也已补齐;修复上述内容后请重新请求复审。
@@ -1229,3 +1231,3 @@- 背景:`/editor/canvas` 生成视频需要严格对齐火山 Seedance 2.0 多模态参考输入;参考视频若继续走 Base64 / `data:video` 会超过请求体并被上游拒绝,参考音频单独输入和非 Seedance 模型携带参考字段也会违反文档契约。- 决策:仅 `seedance2.0-fast` / `seedance2.0` 可提交参考图片、参考视频、参考音频;图片 0~9、视频 0~3、音频 0~3,音频必须搭配图片或视频。参考视频只能提交公网 URL、`asset://` 或画板资源 `objectKey`,禁止 `data:video/*`;视频 / 音频上传先走 OSS 直传和 asset*object confirm,前端保存 signed URL 预览但提交优先 `objectKey`,后端统一重新签名给 Ark。Ark body 按 `image_url` / `video_url` / `audio_url` + `reference*\*`role 构造,并显式发送`generate_audio:false`。- 决策:仅 `seedance2.0-fast` / `seedance2.0` 可提交参考图片、参考视频、参考音频;图片 0~~9、视频 0~~3、音频 0~3,音频必须搭配图片或视频。参考视频只能提交公网 URL、`asset://` 或画板资源 `objectKey`,禁止 `data:video/*`;视频 / 音频上传先走 OSS 直传和 asset*object confirm,前端保存 signed URL 预览但提交优先 `objectKey`,后端统一重新签名给 Ark。Ark body 按 `image_url` / `video_url` / `audio_url` + `reference*\*`role 构造,并显式发送`generate_audio:false`。这里原本的权威约束是“图片 0
9、视频 03、音频 0~3”,当前被格式化成0~~9 / 0~~3,Markdown 会把中间内容解释成删除线,导致共享决策与 RAG 读取到错误数量范围。这属于钱包变更范围外的语义损坏。请恢复原约束,建议把三个范围分别写成行内代码(例如0~9、0~3)以避免 Prettier 再次改写。复审确认旧 review 中的钱包并发、账号生命周期和任务轮询问题均已修复。当前 head 仍有 1 个 P2 阻断:兼容响应只有
walletBalance、没有mudPointBalance时,个人中心统计卡与图片编辑器顶部会丢失可用的 legacy 总额。请把 owner 匹配的 legacy 总额传给这两个总额展示入口;明细仍应保持为空,避免伪造分桶数据,并补齐两处回归测试。修复后请基于新 head 请求复审。
@@ -544,3 +563,1 @@? formatDashboardCount(dashboard.walletBalance): '暂不可用'}value={formatWalletBalance([P2] 这里把个人中心统计卡只绑定到
mudPointBalance;图片编辑器也在ImageCanvasEditorView.tsx中只用mudPointBalance?.totalPoints。复现兼容响应{ walletBalance: 37 }(无mudPointBalance)时,PlatformEntryActiveFlowShell已经算出 owner 匹配的legacyWalletBalance,充值弹窗和空账单能显示 37,但传到这里仍是null,因此个人中心显示“暂不可用”,图片编辑器顶部也不显示余额。请把同一 legacy 总额传给这两个只展示总额的入口,同时让明细继续保持null,不要伪造分桶数据;补两处 legacy 回归测试。226c3f9c32to8405aa3af1当前仍有一个账号隔离相关的阻塞问题:充值下单、邀请码兑换和奖励码兑换这三条写请求没有绑定账号生命周期的 AbortSignal。现有 owner/revision 门禁只能阻止旧请求回调覆盖 UI,不能取消已经发出的服务端副作用;同时 PLATFORM_PROFILE_WRITE_RETRY 会自动重试 POST,fetchWithApiAuth 每轮重试又会重新读取当前 Token。这样 A 账号发起请求后切换到 B,如果请求进入 401、503 或网络重试,旧操作可能改用 B 的凭证创建订单或兑换代码。
建议给这三条写请求绑定账号生命周期 AbortController,在切号和卸载时中止请求,并补充测试,证明 signal 已中止后不会继续 retry。
另外,旧 GET 覆盖刷新、任务 bootstrap 失败后仍轮询、legacy 余额伪造这几项已修复。当前格式门禁仍有 5 个文件未通过 Prettier 3.3.3;提交 7ecb883057 的标题为英文且正文为空,也不符合仓库提交规范。
当前 head 仍有 1 个 P1 账号隔离阻断:业务 AbortSignal 只中止对共享 refresh Promise 的等待,不能取消底层
/api/auth/refresh,而refreshAccessToken完成后仍会无条件发布 token。A 的写请求收到 401 并开始 refresh 后切到 B,A 的调用链虽然不会重放 POST,但旧 refresh 晚到仍会覆盖 B 的 token;我用当前实现确定性复现得到fetchCalls=2、storedToken=late-account-a-token。后续 B 页面请求因此可能携带 A 的凭证。请给 token 发布绑定账号/auth generation 或等价 CAS,确保旧 refresh 不能覆盖新账号状态,也不能让 B 加入 A 的共享 refresh Promise;补齐相应回归测试。旧 GET 快照、任务 bootstrap 轮询、legacy 余额及业务 POST 重放问题已确认修复。
另外,提交
7ecb883057仍是英文标题且正文为空,请按仓库提交规范整理。@@ -665,0 +740,4 @@await refreshResponse.promise;await Promise.resolve();expect(fetchMock).toHaveBeenCalledTimes(2);这里仅断言中止后没有第三次业务 POST,却没有验证晚到 refresh 不会改写新账号 token。当前时序中先写入
account-b-token、再 abort、最后 resolvelate-refresh-token,底层共享refreshAccessToken仍会在apiClient.ts无条件调用setStoredAccessToken,实测最终 token 变成旧账号返回值。请先为 refresh/token 发布增加 auth generation 或 CAS,再在此等待 refresh 完整收束并断言 token 仍为account-b-token;同时覆盖 B 不复用 A 的共享 refresh Promise。654edcb527tof2df562099当前 head 仍有 1 个合并阻断:
src/services/apiClient.ts未通过仓库锁定的 Prettier 3.3.3。仅有两处Boolean(...)续行缩进与格式化输出不一致。请按仓库 Prettier 格式化该文件后重新请求复审。@@ -785,3 +871,3 @@let hasAuthHeader = Boolean(requestHeaders.Authorization?.trim() ||requestHeaders.authorization?.trim(),requestHeaders.authorization?.trim(),这里与下方同类
Boolean(...)表达式的续行缩进不符合仓库锁定的 Prettier 3.3.3;同文件还有一处同样问题。prettier --check src/services/apiClient.ts会失败。请运行该文件的 Prettier 格式化并提交结果,避免 CI/本地格式门禁不一致。