完全指南:注册、触发调用、命名空间路由与内置函数体系)
iii 项目函数Functions完全指南注册、触发调用、命名空间路由与内置函数体系【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii导读在 iii 项目中函数Function是可被任意位置调用的最小业务单元Worker 通过registerFunction/register_function注册一个service::name形式的函数 ID此后无论是iii trigger命令行、进程内 SDK 调用worker.trigger还是 http、cron、queue、state 等事件源绑定都能以完全相同的调用路径命中该函数。本文以 docs/next/using-iii/functions.mdx 为主线结合 Node/TypeScript、Python、Rust 三套 SDK 的源码实现与引擎侧路由逻辑完整讲解函数注册、触发方式、TriggerAction投递语义、命名空间路由规则、CLI 调试技巧以及引擎自带的engine::*内置函数族读完即可在自己的 iii 项目里写函数、调函数、排函数。注册一个函数在 Worker 内部worker.registerFunction(id, handler)Python 为register_function把一个函数注册进 iii 系统使其可以从系统的任何位置被调用。函数id遵循service::name形式例如math::addservice即服务/模块前缀name为函数名handler接收调用的 payload并返回结果。从 SDK 源码看注册在底层是一条 REGISTER_FUNCTION 协议消息Python 端 iii_types.py 中的 RegisterFunctionMessage 携带function_id、handler与可选的response_format、metadata、invocation等字段Node 端registerFunction注册后会返回一个带unregister()方法的句柄底层发送MessageType.UnregisterFunction消息完成注销见 sdk/packages/node/iii/src/iii.ts。三套语言的注册示例如下完整代码来自关联文档Node / TypeScriptimport { registerWorker } from iii-sdk; const url process.env.III_URL; if (!url) throw new Error(III_URL must be set); const worker registerWorker(url, { namespace: orders }); worker.registerFunction(math::add, async (payload: { a: number; b: number }) { return { c: payload.a payload.b }; });Pythonimport os from iii import register_worker, InitOptions worker register_worker( os.environ.get(III_URL), InitOptions( worker_namemath-worker, namespaceorders, ), ) def add_handler(payload: dict) - dict: return {c: payload[a] payload[b]} worker.register_function(math::add, add_handler)Rustuse iii_sdk::{InitOptions, RegisterFunction, register_worker}; let url std::env::var(III_URL).expect(III_URL must be set); let worker register_worker( url, InitOptions { namespace: Some(orders.into()), ..Default::default() }, ); worker.register_function(math::add, RegisterFunction::new(|input: AddInput| { Ok(serde_json::json!({ c: input.a input.b })) }));三个版本均以III_URL环境变量指向引擎地址并在初始化时声明命名空间Python 的worker_name用于标识 Worker 自身。Node 与 Rust 的 handler 返回值会被序列化为函数结果Python 的register_function还支持传入description并会在function_id为空或重复注册时抛出ValueError见 sdk/packages/python/iii/src/iii/iii.py。注册时附加 JSON Schema要让iii trigger function --help能展示函数的参数与返回结构注册函数时可以为请求 payload 和响应形状附加 JSON Schema。Node 端registerFunction的RegisterFunctionOptions以及 Python 端的response_format字段iii_types.py都支持声明格式。关于在注册函数时创建这些 Schema 的完整方法参见 docs/next/creating-workers/functions.mdx 中Attach request and response schemas一节。触发调用函数函数在触发器Trigger触发时运行。同一个函数可以同时被多种触发类型调用直接 CLI 调用iii trigger、进程内 SDK 调用worker.trigger、以及绑定到 http、cron、queue、state、iii-stream 等事件源 Worker 的触发器。所有调用路径都不会改变 handler 本身的实现——handler 只关心payload 进来、结果出去。直接调用函数最常见的两种方式是在 Worker 代码里用worker.trigger或在终端里用命令iii trigger。引擎会把调用路由到注册了该函数的任意 Worker整个过程不涉及触发器注册。action字段控制投递语义默认不设置action调用会等待函数返回结果或等待配置的超时触发传入不同的TriggerAction可以改变这一行为。CLI 调用iii trigger math::add a2 b3Node / TypeScriptimport { TriggerAction } from iii-sdk; const result await worker.trigger({ function_id: math::add, payload: { a: 2, b: 3 }, namespace: default, // target a specific namespace // action: TriggerAction.Void(), // fire-and-forget // action: TriggerAction.Enqueue({ queue: math }), // route through queue });Node 端trigger的返回值类型由action决定见 iii.ts 的 JSDoc 表格不设action时返回PromiseTOutput同步等待函数返回TriggerAction.Enqueue(...)返回PromiseEnqueueResult引擎确认入队TriggerAction.Void()返回Promiseundefined即发即忘。Pythonfrom iii import TriggerAction result worker.trigger({ function_id: math::add, payload: {a: 2, b: 3}, namespace: default, # target a specific namespace # action: TriggerAction.Void(), # fire-and-forget # action: TriggerAction.Enqueue(queuemath), # route through queue }) # result await worker.trigger_async({...}) # awaitable form for asyncio callersRustuse iii_sdk::TriggerAction; use iii_sdk::protocol::TriggerRequest; use serde_json::json; let result worker .trigger(TriggerRequest { function_id: math::add.into(), payload: json!({ a: 2, b: 3 }), action: None, // action: Some(TriggerAction::Void), // fire-and-forget // action: Some(TriggerAction::Enqueue { queue: math.to_string() }), // route through queue timeout_ms: None, } .namespace(default), // target a specific namespace ) .await?;Rust 的TriggerRequest还显式暴露timeout_ms字段不设置时使用引擎侧配置的默认超时设置后则覆盖为自定义超时毫秒。常见的 TriggerAction 语义默认同步不设置action。调用等待函数返回结果或等待配置的超时触发。TriggerAction.Void()即发即忘fire-and-forget。调用立即返回函数仍然运行但调用方看不到结果。TriggerAction.Enqueue({ queue })由 queue Worker 提供详见 docs/next/using-iii/queues.mdx。把调用路由进一个命名队列带重试语义调用在消息入队后即返回。从 Python SDK 的类型定义看iii_types.pyTriggerActionEnqueue要求queueworker 出现在worker-compose.yaml中并且该 worker 下要有匹配的queue_configs条目否则触发会以enqueue_error拒绝无队列提供方TriggerActionVoid的类型字面量固定为void不返回任何响应。另外Worker 可以提供自己的TriggerAction——每个 Worker 支持哪些 action 类型需要查阅对应 Worker 的文档。在 Python 中所有阻塞方法都有对应的 awaitable 孪生方法trigger_async、shutdown_async、create_channel_async供asyncio环境使用详见 docs/next/reference/sdk-python.mdx。路由到指定命名空间Worker 及其关联的函数可以被命名空间namespace隔离。函数 ID 在每个命名空间内唯一而不是全局唯一state::get可以同时在default、orders、analytics三个命名空间各注册一次。在触发调用时设置namespace字段即可选中其中一个。命名空间解析是**严格strict**的调用显式指定orders则只在该命名空间解析不会回退到别处调用未指定命名空间则在调用方 Worker 自身的命名空间内解析解析失败返回function_not_found错误且错误信息会列出该函数 ID 实际存在的命名空间方便定位。引擎侧的function_not_found错误码在 engine/src/workers/engine_fn/mod.rs 与 engine/src/engine/mod.rs 中均有定义并由引擎测试覆盖例如 engine/src/engine/mod.rs 断言缺失函数的错误码、engine/src/engine/mod.rs 断言无关命名空间解析失败。注意事项iii trigger默认访问default命名空间除非传入--namespace NS跨命名空间调用 Worker 代码的方法参见 docs/next/using-iii/namespaces.mdx 的 Trigger a function in a namespace 一节。函数也可以注册绑定到触发器上例如一个http请求、一个cron调度、一次state变更等。把函数绑定到事件源的方法参见 docs/next/using-iii/triggers.mdx 的 Register a trigger 一节。从 CLI 触发函数iii trigger是开发阶段的实用工具不用写临时代码就能从终端直接运行系统中的任何函数。给任意函数传--help可以看到它的参数与功能描述iii trigger function::id --help从 CLI 实现看iii trigger走的是与系统其余部分完全相同的调用路径--help分支会向引擎查询engine::functions::info获取函数元数据见 engine/src/cli_trigger/help.rs而执行分支则构造带function_id的触发请求并发往引擎见 engine/src/cli_trigger/exec.rs。--namespace NS标志存在的原因正是命名空间路由是严格的——注册在其它命名空间的函数只有显式指定命名空间才可达见 engine/src/cli_trigger/mod.rs 的参数文档。正因为走的是同一条代码路径你可以直接在终端里完成真实工作查看函数是做什么的、应用数据库修改、做状态变更或交互式地尝试任何新的改动。这使得iii trigger成为开发与调试的利器。值得强调的是iii trigger function --help之所以能工作靠的是函数携带的请求/响应格式JSON Schema。注册函数时如何为请求 payload 与响应形状创建这些 Schema参见 docs/next/creating-workers/functions.mdx 的 Attach request and response schemas 一节。内置函数Common functionsiii 引擎与标准 Worker 自带一批函数几乎每个 iii 项目都会用到。它们看起来与你自己注册的函数没有任何区别调用方式也完全一样通过iii trigger或worker.trigger唯一特殊之处是你不用注册它们。引擎函数engine::*引擎自身注册了一小组内省introspection与生命周期函数。完整的请求/响应 Schema 参见 docs/next/reference/engine-protocol.mdx 的 Engine discovery functions 一节。函数作用engine::functions::list列出所有已注册函数。传{ include_internal: true }可包含引擎内部函数。engine::workers::list列出所有已连接 Worker 及其指标。传{ worker_id: uuid }可查询单个 Worker。engine::triggers::list列出所有已通告的触发器类型包含其配置与调用 Schema。engine::registered-triggers::list列出所有已注册的触发器实例绑定。engine::channels::create分配一对流式通道 reader/writer。SDK 将之封装为iii-sdk/helpers中的createChannel辅助函数一般无需直接调用。engine::workers::register发布调用方 Worker 的元数据runtime、version、OS、PID、可选namespace、可选description。SDK 在连接时会自动调用。这些函数在引擎侧由 engine/src/workers/engine_fn/mod.rs 实现。从源码注释可以印证文档描述engine::registered-triggers::list产出的config_summary字符串长度上限为 80 字符CONFIG_SUMMARY_MAX_LEN见该文件第 29-31 行Worker 自报的description被视为不可信的自由文本会渲染到控制台、CLI 与 LLM Agent 界面因此在入口处截断到 280 字符并剥离控制字符WORKER_DESCRIPTION_MAX_LEN第 33-36 行。engine::functions::list默认隐藏标记为metadata.internal true的引擎内部 handler传入include_internal: true才可见第 228-232 行注释engine::workers::list返回的WorkerSummary携带namespace字段——这正是两个 Worker 可以在不同命名空间暴露相同函数 ID这一语义的结构基础第 362-365 行注释。引擎还在同一家族中发布两个订阅触发器subscription triggers把函数绑定到其中之一即可对注册表变化做出响应触发器触发时机engine::functions-available有函数被注册或注销时。engine::workers-available有 Worker 连接或断开时。这两个常量的定义见 engine/src/workers/engine_fn/mod.rsTRIGGER_FUNCTIONS_AVAILABLE/TRIGGER_WORKERS_AVAILABLE。常见 Worker下面每个 Worker 都由一个独立 Worker 进程发布。其函数 ID、payload 形状与每个函数的具体行为以各 Worker 自身文档为准StateKV 风格的状态存储带作用域的 key 命名空间与本文讲的路由命名空间是两回事区别见 docs/next/understanding-iii/namespaces.mdx并提供 create/update/delete 上的响应式触发器。Stream通过 WebSocket 向已连接客户端实时推送iii-stream。Queue持久化、有序的任务处理支持重试、并发限制与死信队列dead-letter queue。Pub/Sub轻量的引擎内主题订阅用于扇出fan-out不提供持久性保证。ObservabilityTrace、日志、指标、告警、采样规则与汇总rollup。这些内置 Worker 与函数机制的组合正是 iii 项目组合、扩展、实时观测每个服务Effortlessly compose, extend, and observe every service in real-time这一设计目标的落点你注册的函数可以被任意触发器以任意投递语义调用而引擎与标准 Worker 提供的engine::*与各 Worker 函数则为内省、状态、流、队列、Pub/Sub 与可观测性提供了开箱即用的基础能力。延伸阅读docs/next/using-iii/triggers.mdx把函数绑定到 http、cron、state 等事件源。docs/next/using-iii/namespaces.mdx命名空间路由与跨命名空间调用。docs/next/creating-workers/functions.mdx注册函数时为请求/响应附加 JSON Schema。docs/next/reference/engine-protocol.mdxengine::*内置函数的完整协议与 Schema。docs/next/reference/sdk-python.mdxPython SDK 的阻塞/异步双接口。SDK 源码Node sdk/packages/node/iii/src/iii.ts、Python sdk/packages/python/iii/src/iii/iii.py、Rust sdk/packages/rust/iii/src/iii.rs。【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考