Files
ttstd-infinite-canvas/docs/design/canvas-consistency-repair.mdx

41 lines
6.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 画布批量生成一致性治理
description: 节点丢失、批次状态、引用解析与持久化边界的调查和修复
---
# 批量生成与画布一致性边界
“素材库里有图”只能证明素材存在,不能证明画布节点已经保存;“屏幕上看不见”也不能直接认定节点被删除。排查应分别核对任务终态、素材资源、编辑器节点数组、已保存画布和视口渲染列表。
### 已确认的问题机制
| 现象 | 可复现或由实现确认的原因 | 当前处理 |
| --- | --- | --- |
| 连线后批次子图提示缺少引用 | 子图继承父图提示词,但把父图到子图的分组边当成媒体输入;原来的第二张参考图因此不在子图槽位中 | 提示词展示与生成提交共用输入解析;分组边不充当参考图,子图无显式输入时继承父批次输入 |
| 并发生成覆盖其他节点或编辑 | 媒体解析跨越异步等待,备用结果回填直接替换等待前的完整节点数组 | 结果准备与提交分离,提交时按目标节点及任务身份合并到最新文档 |
| 内存存在,重新读取后新增节点或编辑消失 | 持久化结果与实时编辑合并后,整份快照被跳过保存;store 已接受新编辑,后续同内容更新也不再触发保存 | 只有与已落盘内容一致的快照才能跳过保存;合并进来的编辑继续进入普通保存队列 |
| 成功子图刷新后被错误汇总或被清理 | 多处只以 `content` 判断结果存在,忽略预览未恢复时的 `storageKey`;父图可能保留旧任务身份 | 批次结果同时识别预览与存储标识;父图统一由子图投影,不携带独立任务身份;清理验证子图归属 |
| 缩放或平移时图片不见 | 空间查询先按预算截断,再过滤折叠节点和屏外缓冲区;真实屏内节点也可能超过硬预算 | 先做可见性过滤,屏内及交互节点不按预算截断;预算只限制屏外预加载 |
| 刷新把未知任务误报为失败 | 最近任务列表不完整或查询失败,却被解释成不存在任务 | 已绑定任务独立恢复;发现失败或未命中保留原状态并提示核对任务中心,不伪造终态 |
这些机制不等于已确认每一份用户现场数据的唯一原因。现场还需检查保存请求、账号作用域、任务 ID、资源 ID,以及刷新前后的画布快照。
### 职责划分
1. **编辑命令与 React 显示分离**:`canvas-editor-state.ts` 同步更新编辑器 ref,再向 React 发布快照。命令里的 updater 不交给 React 重放;节点和连线使用同一规则。加载文档仍可显式替换快照,任务结果不能借用这种全量替换权限。
2. **异步结果只提交自己的变化**:`canvas-generation-task-sync.ts` 准备结果;`canvas-generation-result.ts` 校验目标节点和任务绑定,合并生成字段,保留其他节点、移动、手动尺寸和改名。目标删除或已经换任务时拒绝回填,不复活节点。
3. **持久化继续沿用现有协调机制**:`canvas-generation-consumer.ts` 保留账号作用域锁、revision 合并、幂等标记及持久化确认;真实提交完成前不把普通编辑伪装成已确认生成效果。提交期间的新编辑进入普通保存队列,不能因为生成效果已保存就把新编辑也当作已保存。浏览器本地确认不等于服务端已同步。
4. **父批次是子图结果的投影**:生成完成和刷新恢复都调用 `reconcileImageBatchRoot`,汇总主图、存储标识、素材 ID 和失败数量。成功与失败可以同时存在,例如两张成功、三张失败;父图不再继承旧的单图任务终态。重置任务身份放在无副作用的 `canvas-task-state.ts`,不依赖生成请求服务。
5. **输入关系与分组关系分开解释**:`canvas-resource-references.ts` 统一解析;保留现有 Config 输入优先级和按连线顺序编号的合同,去重并防止批次循环。子图显式输入优先于父批次继承。
6. **媒体身份不依赖预览是否恢复**:有 `storageKey` 的图片不能因为 `content` 暂时为空被当作可删除占位或空白原地生成节点。真正读取资源失败仍需报错;存储标识存在不等于文件已经成功读取。
7. **视口只决定绘制,不决定数据存活**:`canvas-node-visibility.ts` 选择渲染节点,不修改节点数组或持久化内容。折叠等显式隐藏规则继续生效。
### 验证与仍需完善的边界
- 专项行为测试覆盖:并发回填、同步命令、已删除目标、任务重置、缺预览资源、两成三败汇总、分组引用、错误的批次归属,以及同屏 1000 节点超过 280 预算仍可见。
- 存储集成测试调用真实生成消费、store、锁与 revision 合并实现,仅替换浏览器存储及资源输入;模拟两份结果并发提交,并在落盘期间新增、改名和移动节点,最后重新读取存储验证两张成功、三张失败及用户编辑均保留。它不是实际浏览器刷新或真实模型端到端验收。
- 当前任务列表接口按数量返回最近记录,没有精确的画布节点历史任务查询或完整游标分页。没有 taskId 且超出发现窗口的节点不会被自动认定失败,但仍需在任务中心人工核对;后续应增加按节点及提交标识精确恢复的服务端合同,而不是无限放大列表上限。
- 取消屏内节点硬裁剪后,极端缩小、海量节点同屏可能增加渲染负担。后续应采用保留所有节点位置的缩略层/细节层分级绘制,不能再以随机缺失节点换取性能。
- 现有加载、远端同步、历史撤销仍保留各自入口,本次并未迁移成统一的规范化文档 store。跨设备并发编辑和立即关闭页面仍需真实场景验收。
- 已经被旧快照覆盖的历史节点不会由本次修复自动重建。素材可用于重新插入,但原节点位置、连线及提示词只能从历史画布或可核对的任务上下文恢复,不能凭空猜测。