尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
loro.js 分离文档快照导出修复:编码最新状态、版本与前沿并保持检出不变
后端【免费下载链接】loroMake your JSON data collaborative and version-controlled with CRDTs项目地址https://gitcode.com/gh_mirrors/lo/loro点击查看免费下载导读本篇文章围绕 loro.js 仓库中.changeset/loro-js-detached-snapshot.md记录的修复展开当调用方对一个处于detached分离/检出到历史版本状态的LoroDoc执行export({ mode: snapshot })时导出内容现在会携带最新状态latest state、版本version与前沿frontiers与 Rust 端及loro-crdt行为保持一致。读完本文你将理解 detached 文档的快照导出语义、修复前后的行为差异、#encodeSnapshot/#encodeLatestState的底层实现路径以及如何用单元测试与差分测试验证这一行为。背景什么是 detached 文档在 loro.js 中一个文档可以通过以下两种方式进入 detached 状态调用checkout(frontiers)将文档状态回退到某个历史前沿此时#detached true#checkoutVersion被设置为目标版本见 document.ts调用detach()将当前版本固化为检出版本并标记 detached见 document.ts。detached 状态下的文档只能读、不能写document.ts中多处编辑入口会抛出cannot edit a detached document; call attach() first见 document.ts。通过isDetached()可以查询状态checkoutToLatest()/attach()则用于回到最新版本并重新挂载。关键点在于detached 文档的“状态”与其“历史oplog”是两个不同概念。文档可能检出于历史版本V1但其oplog中已经包含甚至是在 detached 期间通过import()接收到的更新最新版本是V2。快照导出如何在这种错位下保持正确正是本次修复的核心。问题修复前的快照导出行为本次变更说明明确指出修复前的问题Before, the export wrote the checked-out state and version next to the full history, so an importer saw an old state as the latest version and a later checkout failed.即修复前对 detached 文档执行export({ mode: snapshot })时导出的**状态部分state是当前检出版本checked-out state**下的状态导出的**版本version**是当前检出版本对应的版本向量但**历史full history**是完整的包含了检出版本之后的所有更新。这样产生的快照文件内部自相矛盾导入方拿到快照后会看到“旧状态 完整历史”的组合。由于快照头部声明的版本是旧的检出版本导入方会把旧状态误认为最新版本而历史中实际存在更新的变更。此时若导入方尝试checkout(latestFrontiers)到达历史真实的最新前沿会因状态与版本不一致而失败造成后续 checkout 无法正确进行。修复后的行为快照始终携带最新状态修复后的语义可以概括为一句话snapshot 模式导出的永远是文档的“最新世界”无论当前是否 detached。源码#encodeSnapshot()的注释直接给出了这条契约见 document.ts// A snapshot always carries the latest state, as in Rust. A detached // documents state (lazy or not) may be at an older version or may miss // updates imported while detached. const latestVersion this.#historyVersion(); const detachedState this.version().compare(latestVersion) ! 0;具体来说修复后导出快照包含三部分全部取历史的最新值快照组成修复前修复后状态state检出版本的状态最新版本的状态#encodeLatestState()版本versionVERSION_KEY检出版本的版本向量历史最新版本向量latestVersion前沿frontiersFRONTIERS_KEY检出版本的前沿历史最新前沿排序后的#historyFrontiers同时变更说明强调“The exporting document keeps its checkout”导出过程不会把源文档“带走”源文档的 detached 状态与检出版本在导出后保持不变。这是通过#encodeLatestState()的“转移后恢复”机制实现的详见下文。源码级实现剖析1.ExportMode与export()分派ExportMode定义了四种导出模式见 types.tsexport type ExportMode | { readonly mode: update; readonly from?: VersionVector } | { readonly mode: snapshot } | { readonly mode: shallow-snapshot; readonly frontiers: Frontiers } | { readonly mode: updates-in-range; readonly spans: readonly { readonly id: OpId; readonly len: number }[]; };export()在commit之后按模式分派见 document.tsupdate走增量更新编码shallow-snapshot走浅快照默认的snapshot模式最终调用#encodeSnapshot()。本次修复影响的正是最后这条路径。2.#encodeSnapshot()统一按最新历史编码#encodeSnapshot()内部有两条分支非 detached 且存在 deferred snapshot惰性快照直接从#deferredSnapshotHistory/#deferredSnapshotState组装FastSnapshot把VERSION_KEY与FRONTIERS_KEY覆盖为最新值其他情况含 detached从#sortedHistory()重建历史条目SSTable 形式随后写入VERSION_KEYlatestVersion的 postcard 版本向量与FRONTIERS_KEY排序后的最新前沿并据此决定状态来源state: detachedState ? this.#encodeLatestState() : this.#encodeDeferredSnapshotState(),也就是说一旦检测到“状态版本 ≠ 历史最新版本”detachedState为真状态部分就会由专门的#encodeLatestState()生成而不是沿用当前检出版本的状态。3.#encodeLatestState()临时前进、编码、再恢复#encodeLatestState()见 document.ts是实现“导出最新状态但不改变检出”的关键记录当前版本current与历史最新版本latest计算两者之间的前进记录allForward与回退记录allRetreat优先采用版本增量转移方式在文档上临时应用版本转移至latest复杂度为 O(delta)惰性编码且未被增量触及的容器保持其编码条目不动然后编码状态若增量转移不可行例如跨越了不可重放的状态则退化为在隔离的 staging 文档上重放一次完整历史forkAt(this.oplogFrontiers())后构建状态存储最后通过finally恢复成功时转移回current失败时#rebuildFromHistory(current)保证不留下部分更新的脏状态。由于#applyVersionTransition在转移前后会被调用两次前进后再回退源文档最终停留在原来的检出版本上——这就是“exporting document keeps its checkout”的机制来源。API 使用场景与注意事项本次修复使得以下典型工作流可以安全运行历史版本快照归档检出到旧版本查看 / 审计随后直接export({ mode: snapshot })生成归档导入方可正确到达最新状态离线 / 懒加载文档的 detached 期导入一个从快照懒加载的文档在 detached 期间通过import()接收更新导出快照时这些更新不会丢失跨端一致性loro.js与 Rust /loro-crdt的快照导出语义对齐混合使用多个实现的客户端不会因“旧状态被当作最新版本”而产生 checkout 失败。注意事项快照导出包含完整历史若只需增量同步应优先使用export({ mode: update, from })浅快照不受影响shallow-snapshot模式仍按指定的frontiers裁剪历史与状态见 document.ts源文档不被移动导出前后isDetached()与检出版本保持不变可放心在 detached 状态下反复导出。测试验证本次修复在 detached-snapshot.test.ts 中通过三个用例覆盖encodes the latest state and keeps the checkout构建两轮提交的历史checkout(first)后导出快照断言导出后源文档仍 detached、前沿与 JSON 值仍停留在first导入方toJSON()与frontiers()/oplogFrontiers()均为最新值且可checkout(latest)成功includes updates imported while detached into a lazily imported document目标文档从快照导入后detach()在 detached 期间接收增量更新再导出快照导入方得到最新值{ m: { x: 2 } }且源文档仍保持 detached、仍显示旧值{ m: { x: 1 } }includes updates imported while detached普通文档检出到旧版本后detached 期间导入其他 peer 的更新导出快照后导入方能读到与对方完全一致的最新 JSON 与前沿。此外差分测试也在持续把关这一语义差分 harness 会在每次操作后比对 Rust 与 JS 两侧的isDetached()状态见 harness.ts而 differential.ts 的模糊测试脚本覆盖了detach/checkout/ 快照导出等组合场景确保loro.js的 detached 快照语义与 Rust 实现长期保持一致。小结本次loro.js的 patch 修复了一个容易踩坑的语义缺陷detached 文档的快照导出不再暴露检出版本的“旧状态 完整历史”矛盾组合而是统一编码最新状态、版本与前沿。从实现上看#encodeSnapshot()负责组装最新历史与元数据#encodeLatestState()通过“临时前进—编码—恢复”的方式导出最新状态且不扰动源文档的检出。若你的应用依赖“历史检视 快照归档 跨端同步”组合升级到包含该修复的版本后快照导入与后续 checkout 的行为将更加稳健、与 Rust 端一致。延伸阅读变更记录.changeset/loro-js-detached-snapshot.md导出实现document.ts 与#encodeSnapshot/#encodeLatestStatedocument.ts导出模式类型types.ts单元测试detached-snapshot.test.ts差分一致性测试harness.ts赞分享后端【免费下载链接】loroMake your JSON data collaborative and version-controlled with CRDTs项目地址https://gitcode.com/gh_mirrors/lo/loro点击查看免费下载相关推荐Road Architect for Unity完全指南从零开始创建专业游戏道路系统Road Architect for Unity完全指南从零开始创建专业游戏道路系统 Road Architect for Unity是一款强大的游戏道路系统游戏开发开发工具如何快速导出飞书文档2025最新飞书文档一键导出工具支持Markdown/PDF/Word全格式如何快速导出飞书文档2025最新飞书文档一键导出工具支持Markdown/PDF/Word全格式 飞书文档导出工具feishu doc export是CLI企业应用如何快速导出飞书文档2025最新飞书文档导出工具全攻略 如何快速导出飞书文档2025最新飞书文档导出工具全攻略 飞书文档导出服务是一款高效的开源工具能帮助用户将飞书文档一键导出为Markdown、PDF和DCLI企业应用上一篇Anarlog 1.4.23 版本深度解析会话洞察、徽章成就与转录稳定性全面升级下一篇Worktrunk 扩展机制完全指南Hooks 生命周期钩子、Aliases 别名与自定义子命令实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

买家电去哪买比较靠谱?认准官方直营,海尔商城周年庆福利一览

买家电去哪买比较靠谱?认准官方直营,海尔商城周年庆福利一览

家中使用多年的冰箱突然不制冷,或是搬入新居需要一次配齐洗衣机、空调等大件,这类场景下用户没有太多时间逐项比对。但各渠道在货源、送装和售后上规则不一,想判断哪家靠谱,往往要先弄清几个问题:货源能不能查到、送装…

📅 2026/10/10 14:17:24
中小鞋企预算有限该怎么配?2026入门级步态与足压分析设备方案

中小鞋企预算有限该怎么配?2026入门级步态与足压分析设备方案

摘要2026年鞋类研发竞争重心由外观转向人体工学与穿戴体验,步态、足底压力数据成为产品研发核心指标,但中小型鞋企受限于科研设备成本高、操作复杂、场景适配差等痛点。本文结合落地经验,提供一套预算可控、实用的入门级步态足压分析设备搭配方案。一、预算受限下的三重现实困境…

📅 2026/10/10 14:17:24
OKX AI 口碑查询指南:用 `agent feedback-list` 查看 Agent 评价与星级信誉(identity-reputation 流程)

OKX AI 口碑查询指南:用 `agent feedback-list` 查看 Agent 评价与星级信誉(identity-reputation 流程)

【免费下载链接】internet-court-skill The trust layer for agent-to-agent commerce — natural-language mandates, ERC-7710 delegated permissions, x402 payments, escrow, and dispute resolution as one open, catch-all Agent Skill / Claude Code plugin. 项目地址&a…

📅 2026/10/10 14:12:24
MORE NEWS

更多资讯

📰

给PL/0增加%和^:运算符优先级与结合性的完整实现指南

简介:这是一份编译原理课程设计资源,围绕经典PL/0教学编译器进行系统性修改与扩充,适合高校计算机专业学生完成课程设计、准备实验报告或答辩演示。基础部分已完成两类扩充:一是新增和-复合赋值运算符;二是加入Pascal风…

📰

如何快速安装Calabash-Android:从环境准备到零踩坑的完整教程

移动开发开发工具 【免费下载链接】calabash-android Automated Functional testing for Android using cucumber 项目地址: https://gitcode.com/gh_mirrors/ca/calabash-android 点击查看 免费下载 Calabash-Android 是一款用于 Android 原生与混合应用的免费开源…

📰

南航编译原理课程设计:Java手写词法与语法分析器实战指南

简介:本资源是南京航空航天大学《编译原理》课程设计的完整实现包,面向计算机专业本科生及编译技术初学者,聚焦词法分析与语法分析核心环节,提供可直接运行、经验证无BUG的工程级实践方案。压缩包共32个文件,涵盖8个关…

📰

用Python实现本地模拟横向联邦学习:从FedAvg到单机可复现实验

简介:面向机器学习初学者与联邦学习研究者的横向联邦学习本地模拟资源,使用Python构建,以公开数据集搭建可复现的单机模拟环境,让没有分布式集群的读者也能体验多客户端协作建模的完整过程。资源从数据加载、模型定义、客户端本地…

📰

Java+SSM+Django仓库管理系统:从业务建模到并发控制实践

基于JavaSSMDjango的仓库管理系统,放在毕业设计和公司信息化项目里都是老牌选题了。但网上能找到的同类源码,大多数只是把增删改查套上一个库存表的壳子,真正能对接“明嘉新材料公司”这类生产制造场景的并不多。这篇内容不是列功能清单&…

📰

YOLO实时物体检测实战:从齿条螺栓螺母裂纹数据集到TensorRT部署

简介:面向工业质检与计算机视觉开发者的YOLO实时物体检测工程包,聚焦齿条、螺栓、螺母及裂缝等目标的识别与定位,适合有深度学习基础的开发者进行算法研究或项目移植;YOLO本身将检测任务转化为单个回归问题,通过网格与…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬