SurrealDB 源码贡献指南:从环境搭建、代码规范到提交 PR 的完整工作流
【免费下载链接】surrealdbA scalable, distributed, collaborative, document-graph database, for the realtime web项目地址: https://gitcode.com/GitHub_Trending/su/surrealdb
本篇指南面向希望向 SurrealDB 开源仓库贡献代码的开发者,系统讲解如何搭建 Rust 开发环境、编译并启动数据库、编写与运行 SurrealQL 语言测试、遵守代码规范与 crate 组织约定,以及从分支命名到合并的全套 Pull Request 工作流。读完本文,你将能够在 SurrealDB 仓库中独立完成一次从代码修改、测试验证到提交合并的完整贡献闭环。
参与开发的整体预期
SurrealDB 是一个开源的、可扩展的分布式文档-图数据库(document-graph database),面向实时 Web 场景。仓库本身欢迎一切类型的贡献,包括新功能、缺陷修复、文档改进、博客思路与工作坊内容。不过需要理解它的实际协作节奏:绝大多数开发由内部工程团队规划并完成,社区提交的 PR 通常需要等待一段时间才会被审查,很多被合并的 PR 在收到审查前往往要经历数周。
在提交之前,可以先从两个维度评估自己的 PR 前景:
- 关键性(cruciality):这个改动有多重要?
- 规模(size):这个改动有多大?
由此形成两个典型极端:
- 关键且小巧(例如一行代码的缺陷修复):审查和合并都快;
- 不关键且庞大(例如某个新功能的大规模实现):依然有可能被合并,但最好在动手前与团队进行充分讨论。
一些较大的功能特性可能需要先走 RFC 流程。仓库根目录的 CONTRIBUTING.md 正是官方维护的贡献入口文档,本文的所有内容均以它为主线展开。
PR 长时间无人处理怎么办
如果 PR 提交后迟迟没有动静,可以参考以下建议:
- 观察当前活跃度:查看最近更新的 PR 与活跃分支。如果这些 PR 普遍很大,说明团队正在进行大规模开发,工程师可能暂时没有精力审查新 PR;
- 主动讨论:在 Discord 社区中适时提及你的 PR,工程团队成员大多会关注与自己负责代码块相关的频道;
- 补充图片或视频:视觉化的变更演示常常是吸引注意、说明 PR 价值的最有效方式。
同时需要保持心理预期:你的 PR 可能与一个尚未公开的新功能冲突。如果工程团队已经在开发类似功能,出于保密原因甚至无法对 PR 发表评论,这并非针对个人。
代码规范:格式化与 Lint
SurrealDB 使用 cargo 生态的标准命令来保证代码格式和静态检查的一致:
// 使用 nightly rustfmt 进行格式化(仓库内 rust-toolchain.nightly 指定了具体版本) make fmt(或 cargo make fmt) cargo clippy需要说明的是,根目录的 Makefile 本身是一个透传封装:它会检查cargo-make是否可用,然后把所有目标透传给cargo make(任务定义在 Makefile.toml,并进一步扩展 Makefile.ci.toml 与 Makefile.local.toml)。因此实际执行make fmt前,需要先安装cargo-make:
cargo install --no-default-features --force --locked cargo-make在仓库根目录的 Cargo.toml 中,[workspace.lints.clippy]定义了一系列全局 Clippy 规则,例如assigning_clones = "warn"、redundant_clone = "warn"、unwrap_used = "warn"等,所有 workspace 成员共享这些 lint 配置。值得注意的是unused_async = "allow":SurrealDB 在 AST 解析器与执行器中依赖 async 函数来避免栈溢出,所以这条 lint 被显式放行。提交代码前运行cargo clippy并通过这些规则,是 CI 通过的第一步。
仓库结构与 crate 组织
SurrealDB 是一个 Cargo workspace,根目录的 Cargo.toml 中通过members数组列出了全部 crate。官方在贡献指南中给出了清晰的 crate 分类:
主 crate
| crate | 目录 | 职责 |
|---|---|---|
| surrealdb | surrealdb/ | 主 SDK crate,提供客户端与嵌入式数据库功能 |
| surrealdb-core | surrealdb/core/ | 核心数据库引擎、查询执行与存储层 |
| surrealdb-server | surrealdb/server/ | 服务器实现,提供 HTTP、WebSocket 与 gRPC 端点 |
| surrealdb-types | surrealdb/types/ | SurrealDB 值的公开类型,被 SDK 与服务器共用 |
| surrealdb-types-derive | surrealdb/types/derive/ | 用于派生SurrealValuetrait 的过程宏 |
支撑 crate
| crate | 目录 | 职责 |
|---|---|---|
| surrealism | surrealism/ | 用于执行用户自定义函数的 WebAssembly 运行时 |
| language-tests | language-tests/ | 基于.surql文件的 SurrealQL 语言测试框架 |
| fuzz | fuzz/ | 面向安全与稳定性的模糊测试 |
| profiling | profiling/ | 性能剖析工具 |
从源码可以看到,workspace 还包含surrealdb/common、surrealdb/ast、surrealdb/token、surrealdb/parser、surrealml/core等 crate,共同构成完整的分层架构。
新增 crate 的规范
贡献指南对新增 workspace crate 提出了明确要求,以确保结构一致性:
1. 命名约定(层级 crate)
对于层级 crate(某个父 crate 下的子 crate),crate 名应通过把连字符替换为目录分隔符来匹配目录结构:
- crate 名为
surrealdb-types-derive→ 位于surrealdb/types/derive/ - crate 名为
surrealdb-core→ 位于surrealdb/core/
对于根级 crate(工具、测试等),则允许使用连字符:
- crate 名为
language-tests→ 位于language-tests/
2. 位置
根据用途放置 crate:
- 核心数据库功能 → 放在
surrealdb/下 - 工具与测试 → 放在根级
3. 更新 workspace
在根 Cargo.toml 的members数组中加入 crate 路径:
[workspace] members = [ # ... existing members ... "your-new-crate", ]4. 声明 workspace 依赖
如果该 crate 会被其他 workspace 成员引用,还需要加入[workspace.dependencies]:
[workspace.dependencies] # 预发布版本(例如 -alpha、-beta、-rc) your-new-crate = { version = "x.y.z-prerelease", path = "path/to/your-new-crate" } # 或正式发布版本 your-new-crate = { version = "x.y", path = "path/to/your-new-crate" }仓库现有配置正是这一规范的直接体现:例如 Cargo.toml 中surrealdb-core = { version = "3.1.0-alpha", path = "surrealdb/core", default-features = false }与ast = { package = "surrealdb-ast", path = "surrealdb/ast" }都遵循了这套模式。
从源码搭建开发环境
设置开发环境有两种途径:一是使用 Nix 包管理器(自动管理 C/C++ 依赖与工具链),二是手动安装依赖并确保已安装rustup。注意:以下指令面向的是贡献者(代码维护者)的开发环境;如果只想日常使用 SurrealDB,应参考官方安装与集成文档,而不是从源码构建。
doc/BUILDING.md 详细记录了在 macOS、Ubuntu、Debian、Windows 等多个平台上的编译步骤,包括交叉编译到
aarch64-unknown-linux-gnu、x86_64-unknown-linux-gnu等目标,并明确指出 Windows 编译需要管理员权限、部分交叉编译目标(如 Windows GNU、Linux Musl)当前尚不能成功构建。如果遇到环境问题,请优先查阅该文档。
基础环境
# 提示选择时使用默认的 stable 发布通道 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh git clone git@github.com:[YOUR_FORK_HERE]/surrealdb.git cd surrealdb cargo run -- helpcargo run -- help用于验证编译链路与 CLI 入口是否正常。仓库的src/main.rs是根包surreal(见 Cargo.toml 的[package]段)的二进制入口。
启动 SurrealDB 服务器
为了快速启动一个本地数据库实例,可以用--no-default-features显式挑选最小特性集,只启用内存存储、HTTP 与脚本能力:
cargo run --no-default-features --features \ storage-mem,http,scripting -- start --log trace \ --user root --pass root memory这条命令同时展示了仓库 Cargo.toml 中特性开关的用法:storage-mem(内存存储)、http(HTTP API)与scripting(脚本支持)都是顶层 crate 定义的 feature,它们分别透传到surrealdb-server的同名 feature。默认特性集还包含storage-surrealkv、storage-rocksdb、storage-tikv、graphql、surrealism、cli等。
开发时监听代码变更
利用cargo watch在文件变化时自动重新编译并重启:
cargo watch -x 'run --no-default-features \ --features storage-mem,http,scripting -- start \ --log trace --user root --pass root memory'修改监听地址与端口
默认情况下 SurrealDB 在本地 8000 端口运行。需要变更监听地址或端口时,使用--bind:
cargo run --no-default-features --features \ storage-mem,http,scripting -- start --log trace \ --user root --pass root --bind 0.0.0.0:9000 memory运行全部测试
cargo test使用 language-tests 编写 SurrealQL 语言测试
许多测试已经迁移到 language-tests crate,它允许仅用 SurrealQL 配合一个 TOML 配置注释来创建测试,无需编写任何 Rust 代码。这也是当前仓库最主要的新测试提交方式,官方贡献指南给出了完整示例:
/** # The env map configures the general environment of the test [env] namespace = false database = false auth = { level = "owner" } signin = {} signup = {} [test] # Sets the reason behind this test; what exactly this test is testing. reason = "Ensure multi line comments are properly parsed as toml." # Whether to actually run this file, some files might only be used as an import, # setting this to false disables running that test. run = true # set the expected result for this test # Can also be a plain array i.e. results = ["foo",{ error = true }] [[test.results]] # the first result should be foo value = "'foo'" [[test.results]] # the second result should be an error. # You can error to a string for an error test, then the test will ensure that # the error has the same text. Otherwise it will just check for an error without # checking it's value. error = true */ // The actual queries tested in the test. RETURN "foo"; 1 + "1";该 TOML 配置写在/** */(或//!)特殊注释中,运行测试时所有测试注释会被拼接后解析为 TOML。仓库中真实的测试文件,例如 language-tests/tests/self_tests/simple_matching_expression.surql:
/** [test] [[test.results]] match = "true" */ 1;可见[[test.results]]支持value、error、match等多种断言方式。
language-tests CLI 的用法
language-tests/README.md 详细说明了测试运行工具:
# 在 language-tests 目录下运行全部测试(第二个 run 是子命令) cargo run run # 只运行路径中包含 foo 的测试(过滤器) cargo run run foo # 自动为未指定结果的测试填充期望输出 cargo run run --results accept # 覆盖现有结果(需谨慎使用,仅当确认新结果有效时) cargo run run --results overwrite还支持通过--backend指定存储引擎运行测试:
memory或mem(默认):内存存储引擎,测试最快rocksdb:RocksDB 嵌入式引擎(需backend-rocksdbfeature)surrealkv:SurrealKV 文件存储引擎(需backend-surrealkvfeature)tikv:TiKV 分布式引擎(需backend-tikvfeature 与运行中的 TiKV 集群)
cargo run --features backend-rocksdb run --backend rocksdb在测试配置的[test]与[env]表中,还支持wip(已知问题或进行中功能,失败仅告警不阻断)、version(语义化版本要求)、imports(前置导入文件)、timeout、backend、versioned(MVCC 版本化)、auth、signin/signup、capabilities、planner-strategy(新/旧执行器策略)等丰富的控制键,默认值均为安全的保守选择。
构建生产级二进制
调试阶段完成后,构建生产可用的 SurrealDB 二进制:
cargo build --release根 Cargo.toml 的[profile.release]配置了lto = true、codegen-units = 1、opt-level = 3、panic = 'abort'、strip = true,这意味着 release 构建会经过完整 LTO 并剥离符号,体积与性能都面向生产优化。若要为特定平台交叉编译,参考 doc/BUILDING.md 中cargo build --release --locked --target <target-triple>的用法。
性能与可扩展性考量
SurrealDB 被设计为既要快又要能扩展:既支持单节点部署,也支持分布式集群(分布式模式下基于 TiKV)。同时它被设计运行在不同环境、不同配置与不同规模下。
因此在贡献代码时,需要特别关注以下指标:
- SurrealDB 启动时间
- 查询执行时间
- 查询响应时间
- 查询吞吐量
- 每秒请求数(Requests per second)
- WebSocket 连接数
- 网络使用量
- 内存使用量
仓库中与这些指标直接对应的工具包括 profiling/(性能剖析)与 surrealdb/benches(Criterion 基准测试,覆盖 array、hash trie、HNSW 索引、解析器与执行器等)。当你的改动涉及存储层、索引或执行器时,运行相关基准是很有说服力的佐证。
安全与隐私
SurrealDB 团队非常重视代码、软件与云平台的安全。如果你认为发现了安全漏洞,请立即通过邮件 security@surrealdb.com 报告,而不是在 GitHub 上公开创建 issue。报告时请附上:
surreal version命令输出的版本标识符;- 漏洞可利用方式的详细说明。
在开发过程中,也请遵循行业最佳实践与标准。
外部依赖管理
请避免未经团队讨论就引入新的依赖。新依赖虽然可能带来便利,但也会引入新的安全与隐私问题、增加复杂度,并影响最终 Docker 镜像的体积。添加依赖应当对产品有至关重要的价值,同时把风险降到最低。
仓库根目录的 supply-chain/ 目录(包含audits.toml、config.toml、imports.lock)与 deny.toml 体现了这一治理策略:依赖准入是受控流程,而不是随手添加。
Revisioned structs 与 revision-lock
SurrealDB 使用Revision机制来管理内部类型的版本:如果这些类型的定义发生变更,必须同步更新对应的版本号。为追踪这些版本,仓库使用revision-lock生成锁文件。
根目录的 revision.lock 就是一个实际的锁文件示例,例如:
AccessDefinition:1(surrealdb/core/src/catalog/schema/access.rs)(3072791384) EventDefinition:3(surrealdb/core/src/catalog/schema/event.rs)(3537595141) Relation:2(surrealdb/core/src/catalog/table.rs)(3166613370)每行记录了类型名、当前修订版本号、定义位置与哈希校验。如果 CI 中的 revision.lock 检查失败,安装并运行校验工具即可:
cargo install revision-lock revision-lock这条命令会根据源码中的#[revision]派生宏重新生成/校验锁文件。修改了任何被 Revision 管理的类型(如新增字段、改变序列化格式)却不同步更新版本号,就是这类 CI 失败的典型原因。
善用 issue 的 topic 标签
SurrealDB 的 GitHub issue 带有以topic:开头的标签,例如topic:typing、topic:record ids。在解决某个 issue 时,引用这些标签相关的 issue 往往能带来更深的理解,甚至顺带解决其他相关问题。提交 PR 之前先搜索一遍相关标签,是提高贡献质量的小技巧。
提交 Pull Request 的完整工作流
分支命名:第一层上下文
分支名是给任务提供上下文的第一机会。命名约定为:
TYPE-ISSUE_ID-DESCRIPTION强烈建议把相关 GitHub issue 编号与简短描述结合。如果没有对应 issue,可以省略前缀,但通常最好先创建 issue。例如:
bugfix-548-ensure-queries-execute-sequentially其中TYPE可以是:
- refactor:既不修复 bug 也不增加功能的代码改动
- feature:新增功能的代码改动
- bugfix:修复 bug 的代码改动
- docs:仅文档改动
- ci:与 CI 系统相关的改动
提交信息规范
- 总结要具描述性:提交信息第一行应是对改动的简明总结,不超过 50 个字符,且易于理解;
- 正文提供更多细节:解释你解决的问题、所做的改动以及背后的推理;
- 善用提交历史:小而自包含的提交能让审查者仅通过阅读提交历史就理解整个 PR 的解决思路。
创建 PR 的要点
- 标题清晰且具有描述性,简洁概括改动内容;
- 描述要详细:解释改动推理、解决的问题及对代码库的影响。记住审查者并没有参与你的任务,你需要解释为什么这样写代码;
- 提供背景:在描述中关联相关 GitHub issue、PR、项目或第三方文档链接;如有潜在缺陷或权衡,也要提及;
- 请求审查:向合适的人(维护者、其他贡献者、熟悉该代码库的人)发起审查请求。
如何获得更好的审查
- Draft PR:将仍在进行中的工作以草稿 PR 形式分享,不急于合并或请求即时反馈;
- 积极回应反馈:根据审查意见做出修改、回答问题或表达感谢;
- 使用 re-request review:修改完成后提醒审查者重新查看;
- 利用 CODEOWNERS:仓库的 CODEOWNERS 文件可以指定每个目录的负责人,自动把 PR 分配给合适的人。
完成变更
- 团队积极使用评论线程进行针对性的详细讨论;已解决的线程意味着对话已处理、问题已解决。评论线程由审查者负责 resolve,作者只需回复说明已完成或婉拒;
- PR 获批后,团队会负责任地合并,可能还会运行额外测试或检查以确保代码库仍然可用。
标准流程总结(Summary)
一个标准的 issue 解决流程如下:
- 克隆
surrealdb仓库到本地:git clone https://github.com/surrealdb/surrealdb(可选)安装 pre-commit 以在每次提交前运行检查:
pre-commit install - 创建新分支前先从 upstream
main拉取全部变更,确保本地main是最新的:git pull - 从
main创建新分支,例如bugfix-548-ensure-queries-execute-sequentially:git checkout -b "[the name of your branch]" - 修改代码,并确保所有代码变更格式正确:
cargo fmt - 完成后提交变更:
git add -A git commit -m "[your commit message]" - 推送到 GitHub:
git push origin "[the name of your branch]" - 到你的 GitHub 仓库点击
Compare & pull request提交审查; - 确保提交信息详细说明了改动内容与 PR 的目的;
- 点击
Create pull request提交 PR; - 等待代码审查与批准;
- 批准后合并 PR。
除了 PR,还有更多贡献方式
PR 固然重要,但还有许多其他参与方式:
- 博客与演讲:撰写关于 SurrealDB 特性的博客、教程或演讲,可以联系社区获得推广支持;
- meetup 分享:在 meetup 与会议上分享你的 SurrealDB 项目经验;
- 反馈、bug 与想法:通过 GitHub Discussions、Discord 反馈使用体验,通过 GitHub Issues 提交 bug;
- 文档改进:提交文档更新、增强、设计或修复拼写/语法错误;
- 加入社区:参与官方博客、开发者社区、Discord 等渠道的讨论。
维护者专用:发布流程
如果你是有发布权限的维护者,请参阅完整的发布流程文档。该文档涵盖:
- 如何执行 nightly、预发布(pre-release)、稳定版(stable)与补丁(patch)发布
- 分支策略与版本管理
- 带示例的分步操作说明
- 常见问题的排查
- 工作流架构与幂等性保证
发布是仓库协作链条的最后一环,理解它有助于贡献者把握版本节奏,也有助于维护者标准化操作。
【免费下载链接】surrealdbA scalable, distributed, collaborative, document-graph database, for the realtime web项目地址: https://gitcode.com/GitHub_Trending/su/surrealdb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考