修复 AGC 换号后整项目快照重传:索引按账号分桶,不再整项目重发(#504) #505
Closed
suzmii
wants to merge 2 commits from
fix/api-timeout into master
pull from: fix/api-timeout
merge into: GenarrativeAI:master
GenarrativeAI:master
GenarrativeAI:feat/external-scene-generation
GenarrativeAI:feat/tribo3d-integeration
GenarrativeAI:fix/mobile-style
GenarrativeAI:feat/msg-queue-to-rust
GenarrativeAI:opt/test-compile-warning
GenarrativeAI:codex/admin-gray-game-publish
GenarrativeAI:codex/remove-agc-codex-restrictions
GenarrativeAI:feat/gptimage2to2.5
GenarrativeAI:backup/agc-macos-dualarch-node-runtime
GenarrativeAI:feat/Crt_Ws
GenarrativeAI:codex/preview-llm-router-config
GenarrativeAI:fix/stroke-width-regression-from-285
GenarrativeAI:agent-organize
GenarrativeAI:feat/game-agent-canvas-resource-workbench-v2
GenarrativeAI:feat/agc-new-workflow
GenarrativeAI:fix/agc-release-version-sync
GenarrativeAI:codex/shared-components-followup
GenarrativeAI:codex/game-agent-runtime-interaction-design
GenarrativeAI:feat/spine-sequence-export-v2
GenarrativeAI:codex/game-agent-run
GenarrativeAI:codex/ui-spritesheet-durable-transaction-latest
GenarrativeAI:feat/art-agent-more-tools
GenarrativeAI:codex/editor-canvas-null-source-repair
GenarrativeAI:hotfix/editor-layout-2mib
GenarrativeAI:codex/showcase
No Reviewers
Labels
Clear labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Breaking change that won't be backward compatible
Something is not working
Documentation changes
Improve existing functionality
New functionality
This is security issue
Issue or pull request related to testing
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Low
4
The priority is low
Priority
Medium
3
The priority is medium
Reviewed
Confirmed
1
Issue has been confirmed
Reviewed
Duplicate
2
This issue or pull request already exists
Reviewed
Invalid
3
Invalid issue
Reviewed
Won't Fix
3
This issue won't be fixed
Status
Abandoned
3
Somebody has started to work on this but abandoned work
Status
Blocked
1
Something is blocking this issue or pull request
Status
Need More Info
2
Feedback is required to reproduce issue or to continue work
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: GenarrativeAI/Genarrative#505
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "fix/api-timeout"
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?
关联 #504(本 PR 修的就是它定位到的根因 A),下游症状见 #490。
问题
换号后打开项目会整项目重传一遍:真机复现(CDP attach dev 客户端 + 点「春卷冲刺」)是一次同步重传 2311 个文件、约 3 分钟、2311 次
POST /api/agc/project-snapshots/files(其中 2306 次服务端 HEAD 命中,纯白跑),本地 api-server 日志被刷屏;同窗口内/api/runtime/frontend-config、/api/llm/models、/api/profile/recharge-center在服务端 200 且 ≤61ms 返回的情况下被客户端报「请求超时(15000 ms)」,界面同时失去响应。原因
<AppData>/project-snapshots/<projectId>/index.json整份只保存一个账号的基线,同步前用previous.user_id == session.user_id判等,不等就换成空基线;而远端对象键第一段正是userId。于是:本机 6 个索引文件里有 4 个不同
userId,09-23 19:47 / 09-23 20:47 / 09-24 10:57 三次同形态全量重传,服务端logs/api-server/*.log与客户端diagnostics/application.log的project_snapshot.sync.*两侧对得上。白跑请求本身完全静默(HEAD 命中即200 + skipped),只有服务端日志量能看出来;客户端 15s 超时的那一层在 webview 的定制协议 IPC(刷屏时IPC custom protocol failed … TypeError: Failed to fetch≈0.7 次/秒,空闲时段 847 行日志里只有 59 次)。改动
project_snapshot/index.rs:索引文件升级为 schema v2,结构改为baselines: { userId → 该账号基线 }。读只读当前账号的桶,写只替换当前账号的桶。project_snapshot/mod.rs:同步改用read_project_snapshot_baseline/write_project_snapshot_baseline,删掉user_id判等换空索引的分支;ProjectSnapshotStateView增补baselineCount/baselinePresent,并把fileCount/syncRevision/syncedAtMs改成当前登录账号的口径(此前会把另一个账号的基线报成本账号的)。schemaVersion选分支,v1 文件按它记录的userId迁移进对应桶(userId为空或projectId不符则丢弃),v1 缺失的projectName/pendingFiles迁移后仍是「完整性未知」,不伪造已完成。文件保持 v1 形态直到下一次成功同步写回 v2,所以升级本身不产生额外重传。docs/project-memory/shared-memory/decision-log.md与pitfalls.md。验证
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_snapshotcargo fmt --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --checknpm run check:encoding、git diff --check未覆盖(另开事项)
一次「项目 + 新账号」的新组合仍会把项目全量发给服务端(服务端逐个 HEAD 跳过)。要彻底消掉这批白跑请求,需要客户端可读的远端清单或批量存在性探测;定制协议 IPC 在压力下的失败原因也还没定位(#504 的「待补证据」)。
按「数据与 IO 往后端挪」的架构方向关闭本 PR,不在客户端侧落地。
结论:本 PR 修的那一层(“哪些文件需要上传”的基线判定)正是可以上移到后端的那一层;在客户端本地索引上再落一套,会与迁移后的实现形成两套基线。代码保留在分支
fix/api-timeout(实现 commit3be8e40bc,定向测试 26 passed / 0 failed),迁移完成后若 #504 描述的问题仍在,可直接复用该分支或重开本 PR。诊断现场数据与复现步骤都在 #504。分层说明(回应“是否涉及协议层”):本 PR 只碰本地持久化格式(
index.json)与一个 native-only 诊断视图的字段(read_local_project_snapshot_state的baselineCount/baselinePresent),没有触碰客户端与服务端的路由、DTO、对象键和清单结构,即不涉及协议层。差异判定上移到后端时新增的 manifest / diff 交互才是协议层变更。交给迁移侧的三条约束(不随实现位置改变):
(userId, projectId)两元组归属——远端对象键第一段就是userId,换号后旧基线对新账号无效,任何新设计都不能跨账号共用或互相覆盖。扫描 + 读字节 + 发字节必须留在客户端,“差异判定”才是可上移的那一层。已同步记录到共享记忆(
docs/project-memory/shared-memory/decision-log.md、pitfalls.md的 2026-09-24 条目)。Pull request closed