批处理条件发布
全库目录221
本文目录9
A、B、C三个资产按GUID形成固定计划,A已经发布,B生成到一半时用户取消。本文说明计划哈希、条件发布、检查点与工具版本如何决定重跑的起点。普通对象手势见编辑手势与撤销,同时修改对象和文件时采用跨资源编辑恢复。
批处理与失败恢复
计划先固定输入与发布前提,执行器再生成不可变输出并条件切换正式版本。检查点和发布回执共同区分计算未完成、已经发布和发布后冲突。
计划预览与稳定执行
批量重命名先冻结输入并按GUID排序,生成完整的旧路径、新路径和引用映射。目标重名、大小写冲突、只读状态与缺失类型在这个阶段暴露。A、B交换名称时,计划包含临时名和反向步骤,执行期间不重新枚举半数已经改名的目录。已经符合目标的项标记为跳过;同一输入和参数再次规划得到相同最终状态。
预览直接展示这份计划里的修改、跳过、覆盖、失败项及不可撤销操作,正式执行读取同一份计划。计划生成后用户继续编辑,执行前的版本比较会拒绝过期计划,避免预览和实际修改脱节。后台可处理冻结输入,宿主对象操作则派发到允许的主线程。
每项有自己的状态和恢复记录,批次保存稳定输入列表、完成数量及检查点。并行生成使用独立暂存目录,发布在受控入口串行化或按互不相交的资源锁分组。文件输出先写临时文件,刷新语言缓冲并同步文件,再关闭、重读验证并进入发布;多文件输出形成一个不可变版本目录和清单。正式读者只从已提交的版本指针进入,生成到一半的目录还不是正式结果。
条件发布与检查点恢复
工作项键由资产GUID、输入内容哈希、工具版本和参数哈希组成。计划同时记录输出当前的代次g及内容哈希,暂存结果具有期望哈希H。输入版本决定这份计算是否仍适用,输出代次决定它是否仍有权发布;两者分别检查,源资产没变并不意味着正式输出没被人编辑。
将结果写到独立的不可变版本目录,刷新缓冲、同步文件并关闭,重新读取核对H,再进入短的发布事务。事务条件比较输入版本和输出代次仍与计划一致;成立时,把资产的当前版本指针从g切到g+1,并同时保存工作项ID、H和发布回执。读者先读指针,再读该版本目录,因此不会看到半套输出。最后的Succeeded是报告状态,可以在发布事务之后补写;证明发布发生的是与指针共同提交的回执。
Plan: save input hash, tool/config hash, expected output generation g
Build: write immutable output version; validate content hash H
Publish transaction:
compare current input hash and current output generation with Plan
set current output pointer to new immutable version at g+1
save receipt(jobId, g+1, H)
Commit
Checkpoint: mark Succeeded条件比较与指针切换属于同一个原子操作。对普通文件执行“读取哈希→发现一致→替换”仍有检查与替换之间的竞态,单次原子重命名也不会替调用方比较版本。资产服务可用数据库条件更新;本地工具可在覆盖全过程持有所有写入者共同遵守的资产锁。任意外部程序可以直接修改正式路径时,协作锁不成立,工具只能改为输出新的版本路径并报告冲突,由用户选择采用,不能自动声称安全覆盖。
重启看到Running时,先查持久发布回执。同一控制事务查询工作项回执并比较输出代次,未找到回执且代次仍为g,只表示该观察点尚无已提交发布;重新核对输入后可以原工作项ID、固定摘要及期望g续交。发布入口先按ID返回已有回执,再执行条件比较,使仍在途的原请求和续交请求至多发布一次。查询失败保留Unknown,不创建另一身份。存在回执且当前仍是回执中的g+1、哈希H,说明发布已完成,补记Succeeded即可。存在回执但当前代次更大,或内容与H不符,说明发布后发生了其他编辑,标记Conflict并保留当前输出和旧计划;只有重新生成计划并采用当前版本作为前提,才可再次发布。
例如计划看到输出代次10,发布结果成为11,进程在补记成功前退出。用户随后编辑成代次12。恢复时即使源输入没变,也不能把11再次覆盖到12。另一个反例是输出内容先改成别的值又改回原值:内容哈希相同,代次已从10增到12,旧计划仍拒绝。代次单调递增使这种往返修改可见;所有正式写入者都要通过同一发布入口更新代次。
若希望已发布批次整体撤销,保留前一版本指针,并在撤销时条件比较当前仍是本批次的发布代次,再切向旧内容的新代次。直接把代次减回原值会使旧计划再次匹配。多个文件的版本目录与清单切换见 资产构建与发布;其中旧版本只有在没有读者、检查点和撤销记录引用后才能回收。
持久参考实现把内容存为SQLite BLOB,并把代次、发布回执与指针等价的当前资产记录放在同一数据库事务内。它演示了真正原子的条件发布;接入文件目录时,BLOB对应不可变文件及其已验证引用,文件必须先可读,再提交引用。文件刷盘和目录元数据持久性由目标平台提供,数据库事务不能替外部文件完成刷盘。
进度、取消与错误恢复
假设批处理按GUID排序得到A、B、C三个资产。A发布成功后写入Succeeded;B正在生成暂存输出,此时用户取消。执行器只设置取消标记,让B完成当前不可分割步骤,再于发布前检查标记。若尚未发布,清理或保留有状态的暂存输出,将B、C记为Cancelled,A保持Succeeded。若取消发生在B发布之后,则先核验并记入B的检查点,再停止,不能把已发布结果伪装成未执行。
进度由完成项数与总项数计算,3项中A完成时是1/3;新输入枚举完成后冻结总量,避免进度在执行中悄悄缩小。取消后的重跑先读检查点、发布回执和输出代次,核对A仍对应其已发布结果,再验证B、C的前置版本;若A后来被编辑,同样记录冲突而不是覆盖。取消不是事务回滚:若产品要求整批撤销,则须保留全部逆操作并按反序执行,恢复失败继续记录到报告。
错误决定重试位置。参数或资产验证失败时不进入修改步骤,报告具体字段和GUID;文件服务超时可在有限次数内重试,但每次重新核对输入版本、输出代次与发布回执;磁盘满时保留暂存状态,先停止发布;执行器内部异常则保存栈和操作编号,按编辑手势与撤销的步骤账本处理进程内补偿;发布结果已经共同提交时按回执恢复或提交条件逆操作。同一错误反复重试却继续叠加修改,会破坏幂等契约。
编辑器对象只能由允许的线程修改。后台任务可以读取冻结输入并生成计划,主线程执行短事务和发布;完成通知携带计划版本。用户在分析期间又拖动对象时,版本不匹配的旧计划被拒绝并重新分析。仅把整个批处理搬到后台,会违反引擎API线程约束。
工具版本与数据契约
计划的内容由项目规则、工具版本和本次参数共同决定。例如项目规定名称前缀为角色ID,本次输入为角色17,计划输出17_body;用户偏好只保存窗口和最近目录,不能偷偷覆盖前缀,否则界面和CI的同一输入会生成不同结果。三类配置分别保存,参与结果计算的值都进入计划哈希。
配置模式也属于输入。旧配置将长度保存为厘米,新工具使用米时,迁移步骤把100转换成1并更新模式版本,再执行验证。只给缺失字段填默认值会让资产无声缩小100倍。项目锁定工具与依赖版本,升级时用同一组资产比较迁移计划和输出,失败可回到已锁定版本及原始输入;修改过的文件需要前述检查点或版本控制恢复。
界面与命令行共同调用生成计划、验证、执行和报告四个入口。界面增加选择器、预览和取消按钮,命令行把相同字段作为参数并返回退出码;两者使用相同GUID和配置得到相同计划哈希。属性面板的输入范围由领域验证提供,错误直接定位对象和字段,避免另写一套只在面板中成立的规则。
编辑器适配器和运行时数据分开构建。工具可依赖资产数据库和撤销系统,导出的运行时包只保存消费所需数据。以名称修正器为例,运行时读取修正后的资源引用,不加载重命名窗口或资产数据库接口。构建检查从运行时程序集的依赖闭包确认没有编辑器模块;命令行导出则明确启动包含这些模块的编辑器宿主。程序集名称包含Editor本身不能证明依赖隔离成立。
验证方法
验证发布前取消、发布后写检查点前退出、外部编辑以及内容往返但代次变化。界面与命令行使用同一输入时比较计划哈希和输出。
实现与证据
机制链协议样例以SQLite BLOB运行条件发布、发布回执和外部编辑冲突,包含真实子进程强退。文件刷盘、编辑器线程派发与程序集隔离需要目标宿主集成验证。
相关主题
参考资料
- SQLite Atomic Commit:参考实现中条件发布、回执与状态共同提交的本地持久事务依据。
计划、条件发布和检查点属于工具协议;宿主对象API见编辑手势与撤销。