automerge:高效CRDT实现库,支持本地优先应用的数据同步与持久化

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.

分支124Tags184
文件最后提交记录最后更新时间
1 个月前
4 年前
2 年前
6 天前
6 天前
1 个月前
4 年前
3 个月前
4 年前
1 个月前
1 个月前
1 个月前

Automerge

Automerge 标志

主页 主文档 最新文档 ci

Automerge 是一个库,提供多种 CRDT 的高性能实现、针对这些 CRDT 的紧凑压缩格式,以及一种可在网络中高效传输变更的同步协议。该项目的目标是像关系型数据库支持服务端应用一样,支持本地优先应用——通过提供持久化机制,让应用开发者无需纠结于复杂的分布式计算问题。Automerge 旨在成为你的本地优先应用的 PostgreSQL。

在我们的网站上,你可以找到 JavaScript 文档,其中包含教程和 API 参考。本仓库还包含核心 Rust 库,它会编译为 WebAssembly 并在 JavaScript 中暴露,相关文档可在 docs.rs 上查看。最后,在 rust/automerge-c 中还有一个 C 库——如需更多细节,请查看那里的 README。

如果你熟悉 CRDT,并特别关注 Automerge 的设计,请查看二进制格式规范。

最后,如果你想和我们聊聊这个项目,请加入我们的 Discord 服务器!

状态

该项目由一个核心 Rust 实现构成,通过 FFI 暴露到 JavaScript+WASM 和 C,并很快会支持其他语言。Alex(@alexjg)和 Orion(@orionz)正全职维护 automerge,Ink & Switch 的其他成员也在投入时间,另外还有几位维护者。我们最近发布了 Automerge 3,内存占用大约降低到原来的 1/10。

总体而言,我们努力遵循 semver。

JavaScript

@automerge/automerge 包已提供稳定版本。

Rust

当前 Rust 代码库主要围绕为 JavaScript 封装构建高性能后端而组织,因此 Rust 代码的 API 较为底层,文档也不够完善。未来几个月我们会重新完善这部分内容,但目前你需要通过阅读测试、提出疑问,才能弄清楚如何使用。如果你希望构建使用 automerge 的 Rust 应用,可以了解一下 autosurgeon。

仓库结构

  • ./rust - Rust 实现,以及平台特定封装中的 Rust 组件(例如用于 WASM API 的 automerge-wasm,或用于 C FFI 绑定的 automerge-c)
  • ./javascript - JavaScript 库,内部使用 automerge-wasm,但对外提供更符合 JavaScript 习惯的接口
  • ./scripts - 用于维护代码仓库的脚本,包括在 CI 中运行的脚本。
  • ./img - 供 .md 文件使用的静态资源

构建

要构建此代码库,你需要:

  • rust
  • node

如果你希望构建 automerge-c 库,

  • cmake
  • cmocka
  • doxygen
  • ninja

还需要通过 cargo install 安装以下组件:

  • wasm-bindgen-cli
  • wasm-opt
  • cargo-deny

并确保已为 Rust 交叉编译添加 wasm32-unknown-unknown target。WASM 构建还需要 nightly 工具链和 rust-src 组件(具体命令见下面的 macOS 说明);这些会由 automerge-wasm 和 JS 包用于以 panic=unwind 方式构建 std,以便 panic 以 JS 异常形式呈现。

各个子项目(Rust 代码、封装项目)都有自己的构建说明,但要运行 CI 中会执行的测试,可以运行 ./scripts/ci/run。

在 macOS 上

截至 2022 年 11 月 29 日,这些说明已在 macOS 13.1(arm64)上成功用于本地构建。

# clone the repo
git clone https://github.com/automerge/automerge
cd automerge

# install rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# install homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# install cmake, node, cmocka
brew install cmake node cmocka

# install javascript dependencies
npm --prefix ./javascript install

# install rust dependencies
cargo install wasm-bindgen-cli wasm-opt cargo-deny

# get nightly rust to produce optimized automerge-c builds
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly

# add wasm target in addition to current architecture
rustup target add wasm32-unknown-unknown

# Run ci script
./scripts/ci/run

如果你的构建因找不到 cmocka.h 而失败,你可能需要让它了解 homebrew 的安装位置:

export CPATH=/opt/homebrew/include
export LIBRARY_PATH=/opt/homebrew/lib
./scripts/ci/run

Nix Flake

如果你已安装 Nix,这里提供一个 Flake,其中已配置好所有依赖项和一些辅助脚本。

$ nix develop

  ____                                          _
 / ___|___  _ __ ___  _ __ ___   __ _ _ __   __| |___
| |   / _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` / __|
| |__| (_) | | | | | | | | | | | (_| | | | | (_| \__ \
 \____\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|___/


build:deno          | Build Deno-wrapped Wasm library
build:host          | Build for aarch64-darwin
build:node          | Build JS-wrapped Wasm library
build:wasi          | Build for Wasm32-WASI
build:wasm:nodejs   | Build for wasm32-unknown-unknown with Node.js bindgings
build:wasm:web      | Build for wasm32-unknown-unknown with web bindings
docs:build:host     | Refresh the docs
docs:build:wasm     | Refresh the docs with the wasm32-unknown-unknown target
docs:open:host      | Open refreshed docs
docs:open:wasm      | Open refreshed docs
# ✂️  SNIP ✂️

$ rustc --version
rustc 1.82.0 (f6e511eec 2024-10-15) # latest at time of writing

CI 入口点同样由 flake 暴露。GitHub Actions 会调用这些 相同的命令,因此在 Linux 上可以运行完整的非 Windows CI 套件:

$ nix run .#ci

可以在迭代时运行各个任务,例如:

$ nix run .#ci-fmt
$ nix run .#ci-lint
$ nix run .#ci-js-tests
$ nix run .#ci-node18-packaging-test

在 macOS 上,nix run .#ci 会运行 macOS CI 任务所使用的本机宿主测试。 原生 Windows 任务保持独立,因为 WSL 下的 Nix 测试的是 Linux,而不是 Windows。

贡献

请尽量将你的更改拆分为相对独立的提交,每次只修改一个子系统,并编写良好的提交信息,说明更改内容以及做出更改的原因(提交信息宁长勿短)。git blame 应能让未来的维护者大致明白某处代码为何如此。

发布

本仓库中有四个发布产物需要发布:

  • @automerge/automerge NPM 包
  • @automerge/automerge-wasm NPM 包
  • automerge deno crate
  • automerge rust crate

JS 包

NPM 包会在创建新的 Github 发布时由 CI 工具自动发布。这意味着发布新的 JS 版本的流程是:

  1. 在 @automerge/automerge 以及 javascript/package.json 中提升版本号
  2. 向 main 提交包含版本号更新的 PR,等待测试运行并合并到 main
  3. 合并到 main 后,创建形如 js/automerge-<version> 的标签
  4. 在 Github 上创建新的发布,并指向相关标签

这依赖于 actions 环境中可用的访问令牌 NPM_TOKEN。该令牌生成后有效期为 30 天,因此需要偶尔手动刷新。

Rust 包

这要简单得多,但自动化程度较低。发布步骤如下:

  1. 在 automerge/Cargo.toml 中提升版本号
  2. 推送 PR 并在检查通过后合并
  3. 将发布标签设置为 rust/automerge@<version>
  4. 将标签推送到仓库
  5. 使用 cargo publish 发布

项目介绍

一种类似JSON的数据结构(CRDT),可供不同用户并行修改,并可自动合并。【此简介由AI生成】

定制我的领域
366.66 K273访问 GitHub