SpacetimeDB 模块发布完整指南:从 `spacetime build` 到 `spacetime publish` 的构建、发布与迁移实战
2026/9/13 1:10:02 网站建设 项目流程

SpacetimeDB 模块发布完整指南:从spacetime buildspacetime publish的构建、发布与迁移实战

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

本篇指南系统讲解 SpacetimeDB 中模块从源码到线上数据库的全流程:如何针对不同运行时(Rust/C# 编译为 WASM、TypeScript 打包为 V8 JavaScript)构建模块,如何通过spacetime publish创建新数据库或原子化更新已有数据库,以及--break-clients--delete-data--yes等关键选项的适用场景。读完本文,你将掌握模块发布命令的完整参数体系、底层执行链路(crates/cli/src/subcommands/publish.rs)、自动迁移的兼容性边界,以及一套可落地的发布与回滚策略。

发布前必读:理解模块的运行目标

在发布之前,需要先明确模块的编译产物形态,因为不同的服务端语言对应不同的运行时:

  • Rust 与 C# 模块:编译为 WebAssembly(WASM),由 SpacetimeDB 内置的 WASM 运行时执行;
  • TypeScript 模块:通过打包器产出可在 V8 JavaScript 引擎中运行的 bundle,不经过 WASM。

这一区分在源码层面有直接体现:spacetime publish在决定发布产物时会检查wasm_filejs_file两条路径,并携带host_typeWasmJs)查询参数上传给服务端(见 crates/cli/src/subcommands/publish.rs 与 L635 的builder.query(&[("host_type", host_type)]))。因此,发布命令本身并不关心语言的差异,它只关心最终交付的是哪种运行时产物。

模块目录约定

发布时 CLI 会在当前目录下查找模块工程,默认查找顺序为:

  1. 当前目录下的spacetimedb/子目录;
  2. 当前目录本身。

该逻辑实现在default_publish_module_path(crates/cli/src/subcommands/publish.rs):若spacetimedb/目录存在则优先使用,否则回退到当前目录。这解释了为什么官方模板(如 templates/basic-rs/spacetimedb、templates/basic-ts/spacetimedb)统一把模块工程放在spacetimedb/下——发布、构建命令无需额外指定路径即可命中模块。

第一步:构建模块(spacetime build

进入模块目录(通常是项目内的spacetimedb/),执行:

spacetime build

该命令会编译你的模块并校验其结构。从源码看,spacetime build实际完成的工作包括:

  • 解析模块路径(--module-path,缺省时同样遵循spacetimedb/子目录优先的规则,见 crates/cli/src/subcommands/build.rs);
  • 根据模块语言分发到对应的构建任务(Rust / C# / TypeScript / C++,见 crates/cli/src/tasks 目录下的rust.rscsharp.rsjavascript.rscpp.rs);
  • src/目录进行 lint,检查非功能性print语句(默认 lint 目录为src,可通过--lint-dir覆盖或置空关闭);
  • 产出可发布的 WASM 二进制或 JS bundle。

spacetime build常用选项

选项说明
-p, --module-path <MODULE_PATH>模块工程路径,默认spacetimedb/子目录,其次当前目录
--lint-dir <DIR>检查非功能性print语句的目录,默认src,设为空字符串则跳过 lint
-d, --debug以 debug 而非 release 模式构建,适合本地快速迭代,官方注释明确“不建议用于 CI”
--features <FEATURES>透传给构建进程的附加特性(如 Rust 模块的--features feature1,feature2
--dotnet-version <VERSION>指定 C# 项目目标 .NET SDK 主版本(如 8 或 10),缺省时自动检测

:::tip 如果最终目的是发布,则无需单独执行spacetime build——spacetime publish会在需要时自动触发构建。对于全部构建选项,可参考 spacetime build CLI 参考。 :::

第二步:发布前认证(spacetime login

在发布到托管服务之前,需要先通过认证建立身份:

spacetime login

命令会打开浏览器窗口完成认证,认证完成后凭据保存在本地。从 crates/cli/src/subcommands/login.rs 的实现看,登录流程包含如下细节:

  • 默认向https://spacetimedb.com请求一次性 token,然后轮询认证服务器等待用户在浏览器中批准(web_login,L206-L250);
  • 认证成功后换取 SpacetimeDB 登录令牌(spacetimedb_login,L264-L283),并将令牌保存到本地配置;
  • 支持--no-browser(不自动打开浏览器,打印 URL 由用户手动打开)、--token <TOKEN>(直接使用已有令牌跳过整个流程)、spacetime login show(查看当前登录身份,加--token可同时显示令牌);
  • 自托管场景可用--server-issued-login直接向目标服务器登录,但这种登录方式对其他服务器无效。

若未登录就执行发布,CLI 会尝试交互式登录(get_auth_header内部处理,见 crates/cli/src/subcommands/publish.rs);在非交互脚本中可通过--yes=skip-login显式跳过登录提示。

第三步:发布新数据库

发布模块并创建新数据库:

spacetime publish <DATABASE_NAME>

数据库命名规则

<DATABASE_NAME>必须满足正则/^[a-z0-9]+(-[a-z0-9]+)*$/,即只能由小写 ASCII 字母和数字组成,多个单词之间用连字符-分隔(如my-chat-app)。位置参数也接受数据库 identity。该规则定义在 CLI 参考 的 Arguments 小节,并由源码中的validate_name_or_identity执行校验(crates/cli/src/subcommands/publish.rs)。

发布命令的完整执行链路

spacetime publish <DATABASE_NAME>依次完成:

  1. 构建模块(如果尚未构建):通过build::exec_with_argstring触发,可透传--build-options、NativeAOT 与 .NET 版本设置(crates/cli/src/subcommands/publish.rs);
  2. 创建新数据库:若提供了数据库名,则向/v1/database/<name>发送 PUT 请求;若未提供名称,则 POST 到/v1/database(L589-L617);
  3. 上传并安装模块:将程序字节码作为请求体发送(builder.body(program_bytes).send(),L637);
  4. 运行init生命周期 reducer(若模块中定义了);
  5. 开始接受客户端连接

保存数据库 identity

发布成功后,CLI 会输出数据库的域名与 identity。务必保存这个 identity——后续的数据库管理(如spacetime logsspacetime callspacetime describespacetime delete)都要靠它或域名来定位数据库。若目标是官方托管服务(maincloud.spacetimedb.com),还会额外打印 Dashboard 地址(L655-L659)。

第四步:更新已有数据库与自动迁移

对已发布数据库重新执行同一条命令即可完成更新:

spacetime publish <DATABASE_NAME>

服务端会依次进行:

  1. 构建你的模块;
  2. 尝试自动迁移 schema,使旧数据适配新模块定义;
  3. 原子化替换新模块——发布要么整体成功、要么整体失败,不会出现半新半旧状态;
  4. 维持既有客户端连接不中断。

自动迁移的兼容性边界

“schema”指模块代码中声明的表、reducer、procedure、视图及其依赖类型的集合。SpacetimeDB 的自动迁移(详见 自动迁移文档)把变更分为三类:

安全变更(总是允许,不破坏客户端):新增表、新增索引、增删Auto Inc注解、表从私有转公开、新增 reducer、移除Unique约束。

潜在破坏性变更(允许迁移,但未更新客户端可能报错):在表末尾新增带默认值的列、变更或移除 reducer(旧客户端调用会得到运行时错误)、表从公开转私有(已订阅的客户端报错)、仅改访问器名而保留规范名、移除空表(会断开活动客户端)、移除Primary Key注解、移除索引(可能使基于半连接的订阅查询失效)。

禁止变更(自动迁移会直接失败):移除非空表、移除或修改既有列(含类型/规范名/顺序变更)、新增无默认值的列、在表中间插入列、变更表是否用于scheduling、新增UniquePrimary Key约束、更改索引访问器名。

如果你的更新无法自动迁移,应参考 增量迁移文档 中的生产级模式;开发测试阶段可接受数据丢失时,才考虑使用--delete-data整体重置。

破坏性变更:--break-clients

如果更新包含无法自动迁移的破坏性变更,需要显式声明接受客户端被破坏:

spacetime publish --break-clients <DATABASE_NAME>

⚠️警告:这会使尚未升级到新 schema 的既有客户端无法继续工作。

从源码看,--break-clients等价于--yes=break-clients:它跳过“此次变更会 BREAK 既有客户端”的确认提示,但不会在变更会导致数据库数据删除时强制发布(crates/cli/src/subcommands/publish.rs)。真正决定是否清空数据的是--delete-data(见下文)。其底层通过pre_publish接口向服务端上传模块字节码,服务端返回迁移计划;若计划标记break_clients为真,CLI 会提示确认,确认后携带policy=BreakClients令牌执行发布(apply_pre_publish_if_needed,L756-L824)。

如果本次发布是从 1.x 升级到 2.0 的大版本升级,请先阅读 1.x 到 2.0 升级说明。CLI 检测到大版本升级时会要求输入upgrade确认,并提示升级后无法回退到 1.0(见confirm_major_version_upgrade,L345-L368)。

清空数据:--delete-data

彻底重置数据库并删除全部数据:

spacetime publish <DATABASE_NAME> --delete-data

⚠️警告:这会永久删除数据库中的所有数据!

--delete-data(短选项-c)支持三种取值,控制清空发生的时机:

取值行为
always发布到既有数据库前,无条件销毁该模块关联的全部数据
on-conflict仅当发布会遇到无法自动迁移的破坏性 schema 变更时才清空数据
never从不主动清空(默认值);若必须手动迁移,发布将中止

执行always清空前,CLI 会打印This will DESTROY the current ... module, and ALL corresponding data.并二次确认(confirm_and_clear,L325-L343)。在自动化流水线中可用--yes=delete-data跳过该确认——但请务必确认清空是可接受的。

第五步:发布选项全景

spacetime publish的完整签名是:

spacetime publish [OPTIONS] [name|identity]

除上文已讲的参数外,常用选项如下(均来自 CLI 参考):

选项说明
-p, --module-path <MODULE_PATH>模块工程路径(绝对或相对),默认spacetimedb/子目录,其次当前目录
-b, --bin-path <WASM_FILE>直接发布已编译的 WASM 二进制,跳过构建;与--module-path--build-options--js-path互斥
-j, --js-path <JS_FILE>UNSTABLE:直接发布已打包的 JavaScript 文件,跳过构建
--build-options <BUILD_OPTIONS>透传给构建命令的选项,例如--build-options='--lint-dir='
-s, --server <SERVER>托管数据库的服务器昵称、域名或 URL
--parent <PARENT>父数据库的域名或 identity;新数据库继承父库的团队权限,只能在创建时设置,更新时无效
--organization <ORGANIZATION>新数据库归属的组织(名称或 identity),组织成员权限适用于该库;同样只能在创建时设置
--anonymous以匿名身份执行操作
-y, --yes [<YES>]跳过确认提示;见下文详述
--no-config忽略spacetime.json配置
--env <ENV>配置文件的层级环境名(如devstaging
--native-aot对 C# 模块使用 NativeAOT-LLVM 编译(实验性;支持 Windows,以及安装了 .NET 10 的 Linux)
--dotnet-version <VERSION>指定 C# 项目目标 .NET SDK 主版本,缺省自动检测

--yes:跳过各类确认提示

--yes-y)用于自动化场景跳过交互确认。不带值时等价于--yes=all。可精细指定要跳过的提示类别,多个值可用逗号分隔或重复传参:

spacetime publish my-db --yes=migrate,break-clients spacetime publish my-db --yes=migrate --yes=break-clients
--yes取值跳过的提示
all等价于传入下面所有选项
remote“发布到非本地服务器?”确认
migrate迁移确认(例如大版本升级)
break-clients“会 BREAK 既有客户端”确认
skip-login不提示登录,认证采用非交互方式
delete-data“将 DESTROY ... 全部数据”的破坏性确认

注意:值必须用=附着,即--yes my-db会把my-db当作数据库名而非--yes的值(见 crates/cli/src/subcommands/publish.rs 的 clap 定义)。

使用spacetime.json管理发布目标

从 crates/cli/src/spacetime_config.rs 的配置模型看,spacetime publish会优先读取项目根目录的spacetime.json(可通过--no-config忽略、--env切换环境分层)。配置文件以数据库为核心组织目标(databaseservermodule_pathbuild_optionswasm_filejs_fileparentorganization等键,见build_publish_schema,crates/cli/src/subcommands/publish.rs),支持父子目标继承:

  • CLI 传入的数据库名会以 glob 模式匹配配置文件中的多个目标,一次发布多个数据库;
  • spacetime init生成随机数据库后缀时,CLI 传入的名称与配置不一致也会正确合并模块级配置;
  • 若配置中存在多个目标而 CLI 未指定数据库名,会提示指定名称或 identity 以选中单一目标。

这使得把发布目标固化到仓库配置中、团队共享一致的发布参数成为可能。

发布流程的底层调用链

综合以上内容,一次发布在 CLI 侧的完整调用链为(对应 crates/cli/src/subcommands/publish.rs 的exec_with_optionsexecute_publish_configs):

  1. 加载spacetime.json配置(或仅用 CLI 参数),解析出发布目标集合;
  2. 确定module_path与构建选项;若指定--bin-path/--js-path则跳过构建;
  3. 获取认证头(未登录且未加--yes=skip-login时触发登录);
  4. 校验数据库名与 parent;
  5. 本地构建(或读取预编译产物),读取程序字节码;
  6. 对非本地服务器(非localhost/127.0.0.1)执行发布前二次确认;
  7. 若有数据库名,先调用pre_publish接口获取迁移计划(新库返回 404 视为无需迁移),按计划提示迁移/破坏性变更确认,或触发清空流程;
  8. PUT/v1/database/<name>(或 POST/v1/database)上传模块,附加host_typeparentorgnum_replicas等参数;
  9. 解析PublishResult:打印“Created new / Updated database with name/identity”,权限不足时给出建议的新域名。

其中num_replicas为隐藏的 UNSTABLE 选项(--num-replicas),用于指定数据库副本数(L233-L238)。

发布最佳实践

开发阶段

  • 早期开发中数据丢失可接受时,放心使用--delete-data-c=always)快速重置;
  • 使用-d/--debug或单独执行spacetime build加速本地迭代;
  • 为开发、预发、生产分别建立独立数据库,用spacetime.json固化各自目标。

生产阶段

  • 谨慎规划 schema 变更:发布前对照自动迁移的三类兼容性规则逐条检查;
  • 与客户端升级协同:涉及潜在破坏性变更时,先升级客户端再发布--break-clients,把断连窗口降到最低;
  • 优先向后兼容:尽量新增表/reducer 而非修改既有结构,用增量迁移模式处理复杂变更;
  • 保留数据库 identity:作为后续运维操作的定位依据。

发布之后:下一步学习

模块上线后,可以继续深入:

  • 学习连接客户端 与数据库交互;
  • 深入了解表、reducer 与procedure 的定义与生命周期;
  • 查阅自动迁移 与增量迁移 的完整规则;
  • 若使用spacetime dev进行本地热重载开发,参考开发命令文档。

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询