Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ChildSpecBuilder (子任务规格构建器)

语言: English

一句话结论

ChildSpecBuilder 是在 Rust 代码里构造 ChildSpec(子任务规格) 的链式 API(应用程序接口). 配置和 RPC(远程过程调用) 仍应使用 ChildDeclaration(子任务声明). 构建出口是 build() -> Result<ChildSpec, SupervisorError>, 内部会调用 ChildSpec::validate() 做校验.

child-spec.md 的关系: 那篇文档说明声明与规格的分工; 本篇专门讲 Builder 的入口, setter(设置器) 与常见用法.

模块路径

#![allow(unused)]
fn main() {
use rust_supervisor::spec::child_builder::ChildSpecBuilder;
}

模块定义在 src/spec/child_builder.rs. 按项目模块边界规则, 没有 pub use 重导出.

什么时候用 Builder

场景推荐方式
YAML 配置, add_child RPC 载荷ChildDeclaration + TryFrom
测试, examples(示例), 代码里直接拼运行时规格ChildSpecBuilder
只需 worker 默认 bundle(默认值包), 不想写链式调用ChildSpec::worker(...)? (内部委托 Builder)

旧写法 (逐字段赋值) 仍可能出现在历史代码里, 新代码优先用 Builder.

入口方法

方法用途默认值要点
worker(id, name, kind, factory)异步或阻塞 workerChildSpec::worker 一致: Transient 重启, Critical 关键性, TaskRole::Worker
service(id, name, kind, factory)常驻 service(服务)基于 worker 默认值: TaskRole::Service, Critical 关键性
job(id, name, kind, factory)有限生命周期 job(一次性任务)基于 worker 默认值: TaskRole::Job, Optional 关键性
sidecar(id, name, kind, factory, sidecar_config)跟随 primary child(主子任务) 的 sidecar(边车)基于 worker 默认值: TaskRole::Sidecar, 写入 sidecar_config, 并自动加入 primary child 依赖
supervisor(id, name)嵌套 supervisor(监督器)kind = Supervisor, factory = None, task_role = Supervisor, criticality = Critical
new(id, name)最小骨架仅填 id / name 与 baseline(基线) 策略; 调用方需自行补 kind, 以及 worker 所需的 factory

构建出口

方法行为
build()取出内部 ChildSpec, 调用 validate(), 成功返回 Ok(spec), 失败返回 SupervisorError

所有入口方法和 setter(设置器) 都返回 ChildSpecBuilder, 只表示“还在构造中“. 只有 build() 会消费 builder(构建器), 并返回最终 ChildSpec.

没有 build_validated(). 校验统一在 build() 内完成.

ChildSpec::worker(...) 同样返回 Result<ChildSpec, SupervisorError>, 实现为 ChildSpecBuilder::worker(...).build().

基本用法

#![allow(unused)]
fn main() {
use rust_supervisor::error::types::SupervisorError;
use rust_supervisor::id::types::ChildId;
use rust_supervisor::policy::task_role_defaults::TaskRole;
use rust_supervisor::spec::child::TaskKind;
use rust_supervisor::spec::child_builder::ChildSpecBuilder;
use rust_supervisor::task::factory::{TaskResult, service_fn};
use std::sync::Arc;

fn build_worker() -> Result<ChildSpec, SupervisorError> {
    let factory = Arc::new(service_fn(|_ctx| async { TaskResult::Succeeded }));
    ChildSpecBuilder::worker(
        ChildId::new("invoice-worker"),
        "Invoice Worker",
        TaskKind::AsyncWorker,
        factory,
    )
    .task_role(TaskRole::Worker)
    .tag("invoice")
    .build()
}
}

错误用 ? 向上传播, 或在测试里 build().expect("...").

链式 setter 范围

每个 setter 消费 self 并返回 Self, 可任意顺序链接 (在语义允许的前提下).

策略类: isolation, restart_policy, shutdown_policy, health_policy, readiness_policy, backoff_policy

拓扑与分类: dependencies, dependency, tags, tag, criticality, task_role, without_task_role, sidecar_config, without_sidecar_config, severity, without_severity, group, without_group

配置块: health_check, without_health_check, readiness, without_readiness, resource_limits, without_resource_limits, command_permissions, environment, env_var, secrets, secret, cleanup_paths, cleanup_path

运行时: kind, factory, without_factory (供 new() 或 supervisor 路径使用)

命名约定: 复数字段用 dependencies(...), tags(...); 单条便捷方法用 dependency(...), tag(...). environment / env_var, secrets / secret, cleanup_paths / cleanup_path 同理.

常见组合示例

Service (服务)

常驻服务优先使用 service(...), 不需要手动设置 TaskRole::Service:

#![allow(unused)]
fn main() {
ChildSpecBuilder::service(id, "API Service", TaskKind::AsyncWorker, factory)
    .tag("service")
    .build()?;
}

Job (一次性任务)

有限生命周期任务优先使用 job(...). 如果需要一次运行后停止, 可以继续覆盖 restart_policy:

#![allow(unused)]
fn main() {
ChildSpecBuilder::job(id, "Nightly Export", TaskKind::AsyncWorker, factory)
    .restart_policy(RestartPolicy::Temporary)
    .build()?;
}

Sidecar (边车)

跟随主任务的边车优先使用 sidecar(...). 这个入口会写入 sidecar_config, 并把 primary child 自动加入依赖:

#![allow(unused)]
fn main() {
use rust_supervisor::policy::task_role_defaults::SidecarConfig;

ChildSpecBuilder::sidecar(
    id,
    "Metrics Sidecar",
    TaskKind::AsyncWorker,
    factory,
    SidecarConfig::new(primary_id.clone(), false),
)
.build()?;
}

如果仍然用 setter(设置器) 手动设置 task_role = Sidecar, 就必须同时设置 sidecar_config, 否则 build() 校验失败.

new() 拼出 worker

#![allow(unused)]
fn main() {
ChildSpecBuilder::new(ChildId::new("custom"), "custom")
    .kind(TaskKind::AsyncWorker)
    .factory(factory)
    .build()?;
}

数据流 (简图)

ChildSpecBuilder::worker / service / job / sidecar / supervisor / new
        |
        v
   链式 setter (policy, role, deps, env, ...)
        |
        v
   build()  -->  ChildSpec::validate()
        |
        +-- Ok(ChildSpec)  -->  Supervisor::start / 注册拓扑
        +-- Err(SupervisorError)

示例程序

可运行演示:

cargo run --example child_spec_builder

源码: examples/child_spec_builder.rs. 覆盖 worker, service, job, sidecar, supervisor, new() 路径, 以及故意失败的 sidecar 组合.

测试与回归

外部测试: src/spec/tests/child_builder_test.rs

测试验证点
worker_builder_matches_child_spec_worker_defaultsBuilder 与 ChildSpec::worker 字段一致
supervisor_builder_produces_valid_supervisor_childsupervisor 入口无 factory 且可校验
service_builder_sets_service_roleservice 入口设置 TaskRole::ServiceCritical 关键性
job_builder_sets_job_role_and_optional_criticalityjob 入口设置 TaskRole::JobOptional 关键性
sidecar_builder_sets_sidecar_role_binding_and_dependencysidecar 入口设置绑定并自动加入 primary child 依赖
builder_setters_apply_expected_fieldssidecar, dependency, tag 等 setter
build_rejects_invalid_sidecar_combinationsidecar_configbuild() 失败
new_builder_can_build_valid_worker_with_factorynew() 路径补全后可构建

运行:

cargo test --test child_builder_test

已知边界

  • TryFrom<ChildDeclaration> 的默认值 bundle 尚未与 Builder 完全共用; 两处默认值仍可能独立演进, 改默认值时需同时对照声明转换路径.
  • Builder 不负责 serde(序列化/反序列化); 动态加子任务仍走 ChildDeclaration.
  • 未批量迁移历史 examples/tests 中的 ChildSpec::worker; 两种写法在运行时等价 (只要都处理 Result).

进一步阅读