跳到内容
Lenso
简体中文
Esc
导航打开⌘J预览
本页内容

Linked Rust Plugin

实现一个直接编译进产品 Host 的原生 Rust Plugin。

当你拥有 Host 二进制,而且 Plugin 需要普通 CLI 脚手架没有提供的 Capability、 配置、生命周期或状态模型时,选择这条路径。这是最完整的 Rust authoring path。

1. 添加 facade 和 Capability crate

Plugin crate 依赖公共 lenso facade,以及它提供或依赖的生成 Capability crate。 使用 owner repository 已经锁定的同一组 Git revision 或发布版本,不要自行混用 不同版本的框架包。

[dependencies]
lenso = { version = "0.2", features = ["host"] }
serde = { version = "1", features = ["derive"] }
example-greeting-contract = { version = "1" }
example-profile-contract = { version = "1" }

上面的包名用于说明所有权。实际开发时请替换为目标 Host 使用的生成 Capability 包。

2. 定义配置与依赖

use example_greeting_contract as greeting;
use example_profile_contract as profile;
use lenso::prelude::*;

#[derive(Clone, Debug, serde::Deserialize, PluginConfig)]
struct GreetingConfig {
    #[lenso(default = "Hello")]
    prefix: String,
}

#[plugin]
#[derive(Clone, Debug)]
struct GreetingPlugin {
    #[config]
    config: GreetingConfig,
    profile: Port<profile::ProfileClient>,
}

PluginConfig 会生成封闭的配置 Schema 和默认值。Port<Client> 声明必须绑定 一个 provider;只有 Capability Contract 确实接受多个 provider 时才使用 ManyPort<Client>

无状态 Plugin 可以省略 #[config],此时生成的 Contract 只接受空对象。

3. 实现业务行为

#[provides(greeting::Greeting)]
impl GreetingPlugin {
    async fn greet(
        &self,
        ctx: Ctx,
        request: greeting::GreetRequest,
    ) -> Result<greeting::GreetResponse, greeting::GreetError> {
        // Port 通过 Deref 直接暴露生成的 client。
        let _ = (&self.profile, &self.config.prefix, ctx, request);
        todo!("返回生成的 greeting 领域响应")
    }
}

生成代码负责 dispatch、endpoint 构造、类型擦除和 factory 注册。业务方法始终 使用领域类型。只有实现必须显式保留 Runtime Failure,并将它与预期 Domain Error 区分时,才返回 PluginResult<T, DomainError>

一个内聚的 Plugin 可以在同一个注解中提供多个 Capability:

#[provides(greeting::Greeting, health::Health)]
impl GreetingPlugin {
    // 在这里实现两个 Capability 生成的 operations。
}

4. 只在拥有资源时添加生命周期

Plugin 自己拥有连接、worker 或其他必须随 App Generation 准备、激活和释放的 资源时,使用 #[plugin(lifecycle)] 并实现 Lifecycle。如果只需要随 Generation 管理后台任务,而不需要自定义阶段,添加 #[tasks] tasks: ManagedTasks 字段。

5. 从 Host 暴露生成的 factory

宏会注册一个 linked factory。Host 通过原生 registry 让这些 Plugin 可用:

let registry = NativePluginRegistry::new().with_linked_factories();

可用不等于激活。Host Catalog 与 App 的 Plugin Root 仍然决定 Instance 是否存在、 依赖的 Capability 如何绑定。下一步参见向 App 添加 Plugin

6. 证明业务行为

运行 owner repository 的格式化、检查和测试。至少覆盖一次成功调用、所有预期 Domain Error、非法配置、必需 Port 的绑定、适用时的取消,以及两个 Generation 之间的全新生命周期状态。如果同一个 Plugin 有多个实现,用同一组行为用例运行 每个实现。

最后更新于 2026年9月6日

这个页面有帮助吗?