- 语言运行时
- JIT编译
【免费下载链接】wasmer
🚀 Fast and lightweight sandboxes for your apps and AI agents
导读:本文以 Wasmer 仓库中 lib/backend-api/CHANGELOG.md 为主线,梳理wasmer-backend-api这个 GraphQL API 客户端 crate 从 0.1.0-alpha.1 到 0.0.1 两个版本的演进脉络,并结合 client.rs、query.rs、subscription.rs 等源码,带你理解 Wasmer 后端 GraphQL 接口的设计思路、关键能力(包查询、应用部署、令牌生成、日志与订阅)以及如何在自己的 Rust 项目中上手使用。
版本概览:一个客户端,两个关键版本
wasmer-backend-api是 Wasmer 仓库中负责与 Wasmer.io)。CHANGELOG 按时间倒序记录了两次版本发布:
| 版本 | 发布日期 | 性质 |
|---|---|---|
| 0.0.1 | 2023-04-27 | 首个正式发布版(含 3 项修复/变更) |
| 0.1.0-alpha.1 | 2023-03-29 | 预发布版(含 1 项破坏性重构与大量功能迭代) |
值得注意:CHANGELOG 的版本号排序与语义化版本(SemVer)并不一致。0.1.0-alpha.1 在时间上更早(2023-03-29),却包含了破坏性变更(BREAKING);而 0.0.1 是其后推出的"首个正式版",主要内容是收尾性修复。这种"先 alpha 后 0.0.1"的顺序在真实项目演进中并不罕见,阅读变更日志时应当以日期而不是版本号大小来判断先后。
0.1.0-alpha.1:新客户端与破坏性重构
0.1.0-alpha.1 是这个 crate 的"奠基版本",包含一次重要重构、一批新特性、若干 bug 修复以及工程化清理。
破坏性重构:从 wasmer-deploy-core 到 wasmer-deploy-schema
该版本最重要的一项变更是:
Rename wasmer-deploy-core to wasmer-deploy-schema —— schema 是对这个 crate 更贴切、更具表达力的名字,因为它只承载类型定义。
这是在为 crate 正式发布做准备:下游消费者(如 Wasmer 主仓库自身)即将依赖这个 crate,因此需要一个命名准确、语义清晰的类型定义库。从源码结构看,这一重构把"类型定义"(types.rs)与"查询封装"(query.rs)清晰地分离开来,构成了当前 crate 的模块骨架。
新特性:部署令牌、包查询与应用版本查询
CHANGELOG 记录了四个新功能,全部在当前源码中得以印证:
1. 向新的 cynic GraphQL 客户端添加generate_deploy_token
这是"移除旧 API 实现、改用 cynic 客户端"的配套动作(详见下文 Bug Fixes)。当前源码中对应的实现是 generate_deploy_config_token_raw 与 generate_ssh_token,它们分别通过GenerateDeployConfigToken和GenerateSshToken两个 mutation 向后端换取部署令牌:
generate_deploy_config_token_raw目前支持TokenKind::SSH,payload 为"{}",返回GenerateDeployConfigTokenPayload.token;generate_ssh_token支持传入可选的app_id,将令牌作用域限定到特定应用,用于通过 SSH/SFTP 访问 Edge。
对应 schema 侧定义可见 schema.graphql:GenerateDeployConfigTokenInput接受config: String!,GenerateDeployTokenInput接受deployConfigVersionId: String!—— 这印证了 CHANGELOG 中"部署配置按版本(DeployConfigVersion)管理"的设计。
2. 新增getPackageGraphQL 查询
这是包注册表的核心查询。当前实现为 get_package 附近的GetPackage::build(GetPackageVars { name }),配合 get_package_release(按包版本获取发行信息,含webc_url)、get_package_releases(分页列出发行版本)以及 get_package_releases_stream(自动翻页的流式版本)共同构成完整的包查询能力。
3. 新增DeployAppVersion查询
用于按应用+版本获取部署版本详情,对应源码 get_app_version(按 owner/name/version 查询)与 get_app_with_version(同时返回应用和指定版本),还支持通过 get_app_version_by_id 等方式按全局 ID 定位版本。
4. 新增 namespace 与 app 命令
这对应 CLI 侧的app list等命令(详见下文),说明该版本同时在为命令行工具铺路。
新配置:CapabilityLoggingV1 与实例日志转发
CHANGELOG 提到:
新增 CapabilityLoggingV1 配置,允许配置工作负载的日志行为,将很快用于实现实例日志转发(instance log forwarding)。
虽然该配置类型定义在wasmer-configcrate(lib/config),但 backend-api 侧对日志的消费能力可从源码看到:query.rs中存在get_app_logs函数(当前因"流可能因反复拉取相同日志而死循环"的可用性问题被标记为非公开),以及 get_cron_job_invocation_logs_by_invocation_id 用于按调用 ID 直接拉取定时任务日志。这些实现共同验证了"日志转发"这条功能线。
Bug 修复:令牌鉴权与部署配置 API 变更
修复 1:使用令牌抓取 webc 包
如果 API 配置了令牌,抓取 webc 时使用该令牌;此前只使用匿名访问。
对应实现可见 fetch_webc_package。需要注意的是,当前实现主要依赖 registry 的公共 URL(函数注释明确说明"使用公共 URL 而非 API 的 download URL,如非必要不应使用"),并通过ACCEPT: application/webc头与自定义USER_AGENT发起请求。令牌鉴权的核心逻辑则在 run_graphql_raw:当WasmerClient配置了auth_token时,自动为请求附加Bearer令牌头。
修复 2:部署配置生成逻辑适配后端变更
generateDeployConfigGraphQL API 已变更:入参从DeployConfig id改为DeployConfigVersion id,返回值从DeployConfig改为DeployConfigVersion。
这一后端 API 变更在 schema 中留下了直接证据:GenerateDeployTokenInput 接收deployConfigVersionId: String!。它意味着部署配置已经"版本化"管理,令牌与配置版本绑定,而非与配置本身绑定。
工程化清理:workspace 依赖提升
0.1.0-alpha.1 还做了一系列依赖管理优化("Other" 分类):
- 将部分依赖提升到
workspace.dependencies避免重复; - 移除一批未使用的依赖;
- 将
serde、serde_json、anyhow、time、clap提升为 workspace 级依赖,简化版本管理; - 为
wasmer-api的 Cargo.toml 添加 description(发布所需)。
这些工程细节在 Cargo.toml 中仍然可见:serde、serde_json、anyhow、time、tokio、url、futures、tracing均使用workspace = true引用,只有reqwest和cynic等少数依赖在本地声明了 feature。
0.0.1:正式发布的收尾修复
0.0.1 作为正式发布版,只包含三条变更,全部是收尾性工作:
- 移除旧 API 实现,改用新的 cynic 客户端:这是整个 crate 技术选型的最终落定。README 中明确解释了选型原因:cynic 提供了 Rust 类型与 GraphQL 类型之间的紧耦合集成,相比
graphql-client显著减少了样板代码、改善了开发体验(见 README.md); - 修复日志查询(Fixed log querying);
- 新增按唯一 ID 获取 DeployApp/Version 的方法:对应源码中的 get_app_by_id(按全局 ID 取应用)、get_deploy_app_versions_by_id 与 all_app_versions_by_id(按应用 ID 分页拉取全部版本)。这些方法正是 0.1.0-alpha.1 中"新增 DeployAppVersion 查询"的延续——从按名称查询扩展到按唯一 ID 查询。
从变更日志看底层实现:cynic GraphQL 客户端架构
客户端骨架:WasmerClient
CHANGELOG 反复提及的"新 cynic 客户端",其核心是 client.rs 中定义的WasmerClient:
pub struct WasmerClient { auth_token: Option<String>, graphql_endpoint: Url, pub(crate) client: reqwest::Client, pub(crate) user_agent: reqwest::header::HeaderValue, #[allow(unused)] log_variables: bool, }它具备以下关键能力:
- 端点管理:lib.rs 提供开发/生产两个内置端点常量 ——
ENDPOINT_DEV = https://registry.wasmer.wtf/graphql和ENDPOINT_PROD = https://registry.wasmer.io/graphql,以及对应的endpoint_dev()/endpoint_prod()便捷函数; - 鉴权:通过
with_auth_token(String)注入令牌,所有 GraphQL 请求自动附加Bearer认证头(client.rs); - 安全日志开关:环境变量
WASMER_API_INSECURE_LOG_VARIABLES控制是否记录请求变量。源码注释明确警告这"可能记录敏感信息",默认关闭,仅接受0/false|1/true取值(client.rs); - 代理支持:
new_with_proxy支持注入reqwest::Proxy,非 wasm 目标下默认设置 10 秒连接超时、90 秒整体超时(client.rs); - 错误路径:
run_graphql_strict在响应含任何 errors 时即失败(client.rs),而run_graphql只在无 data 时才抛错;错误统一包装为 GraphQLApiFailure。
查询封装模式
query.rs(2746 行)是该 crate 的主体,采用统一的函数封装模式:每个函数用cynic::QueryBuilder::build构造操作、通过client.run_graphql(_strict)执行、再用context/bail做错误归一化。典型示例:
pub async fn get_app_by_id(app_id: String) -> Result<DeployApp, anyhow::Error> { client .run_graphql(types::GetDeployAppById::build(types::GetDeployAppByIdVars { app_id })) .await? .app .into_deploy_app() .context("app conversion failed") }值得一提的还有stream.rs中基于pin-project-lite实现的QueryStream分页流(stream.rs),它把"逐页请求 → 缓冲 → 逐条产出"的迭代逻辑封装为futures::Stream,被get_deploy_apps_stream、get_package_releases_stream等使用——这正是 0.1.0-alpha.1 中"app list 支持过滤 namespace/用户/all"(--namespace X, --all)得以实现的底层机制。
实时订阅:WebSocket 通道
在sysfeature 下(默认开启,见 Cargo.toml),crate 还提供基于graphql-ws-client+tokio-tungstenite的 GraphQL 订阅能力(subscription.rs):
package_version_ready:订阅某个包版本"就绪"事件;autobuild_deployment:订阅自动构建部署的状态更新。
两个函数共享同一套连接逻辑:将 GraphQL 端点的http(s)改写为ws(s),设置Sec-WebSocket-Protocol: graphql-transport-ws,携带Authorization: Bearer <token>(若配置)与自定义 User-Agent,随后通过graphql_ws_client::Client::subscribe建立订阅流。
从变更日志到 CLI:app list 等命令的落地
CHANGELOG 中"新增 namespace 和 app 命令"与"app list 过滤器"两条记录,指向了 Wasmer CLI 的实际能力。在 lib/cli/src/commands/app 目录下,app相关命令的实现正是基于 backend-api 的查询函数构建的。get_deploy_apps(query.rs)接收GetDeployAppsVars,支持按 namespace、按用户、或按用户可访问的全部应用三种模式查询,这与 CHANGELOG 中描述的--namespace X、--all过滤语义一一对应。需要说明:具体的 CLI 参数解析细节在 opts.rs 与 app 子命令中,本文不展开,但可以确认 backend-api 提供了全部所需的查询原语。
上手使用:在你的 Rust 项目中集成 wasmer-backend-api
综合 CHANGELOG 与源码,一个典型的集成流程如下:
- 引入依赖:在
Cargo.toml中声明wasmer-backend-api(当前版本 0.704.0,见 Cargo.toml)。默认启用sysfeature(含订阅支持),在 wasm 目标下可改用default-features = false, features = ["js"]; - 构造客户端:
use wasmer_backend_api::{WasmerClient, endpoint_prod}; let client = WasmerClient::new( endpoint_prod(), // 或 endpoint_dev() "my-app/1.0.0", // User-Agent,不允许为空 )?; // 如需鉴权: let client = client.with_auth_token("your_api_token".to_string());- 执行查询:调用
query模块中的函数,例如获取当前用户current_user(&client)、按名称查包、按 ID 查应用等; - 使用订阅(可选):在
sysfeature 下调用package_version_ready(&client, &id)或autobuild_deployment(&client, &build_id)获得订阅流; - 处理错误:所有查询函数返回
anyhow::Result,GraphQL 层错误会被包装进GraphQLApiFailure并附带上下文信息。
总结
通过这份 CHANGELOG,我们可以完整还原wasmer-backend-api的演进逻辑:先以破坏性重构(wasmer-deploy-schema)奠定类型基础,再以 cynic 客户端替换旧实现完成技术栈统一,随后围绕包管理、应用部署、令牌与日志等能力逐项补齐查询/变更/订阅原语,最终以 0.0.1 收尾发布。对于想要理解 Wasmer 后端 API 生态、或者在自己的项目中复用这套 GraphQL 客户端模式的开发者,query.rs、client.rs 与 schema.graphql 是三个最佳的阅读起点。
- 语言运行时
- JIT编译
【免费下载链接】wasmer
🚀 Fast and lightweight sandboxes for your apps and AI agents
相关推荐
Wasmer Backend API:基于 Cynic 构建的 Wasmer GraphQL 客户端库实战指南
Wasmer Backend API:基于 Cynic 构建的 Wasmer GraphQL 客户端库实战指南 导读 wasmer backend api (目
语言运行时JIT编译Zulip API Feature Level 机制与变更日志深度解读:从版本演进到客户端兼容实践
Zulip API Feature Level 机制与变更日志深度解读:从版本演进到客户端兼容实践 Zulip 的 API 变更日志( api_docs/cha
即时通讯后端前端WebSocketMastra @mastra/client-js 变更日志精读:版本演进脉络与关键客户端 API 实现
Mastra @mastra/client js 变更日志精读:版本演进脉络与关键客户端 API 实现 本文以 client sdks/client js/CH
人工智能Agent 框架AI AgentRAG后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考