资讯动态

iii-sdk(Node.js/TypeScript)实战指南:连接 iii 引擎、注册函数与触发器、调用工作流

发布时间:2026/9/15 4:09:42 来源:尧图企业网站定制
iii-sdkNode.js/TypeScript实战指南连接 iii 引擎、注册函数与触发器、调用工作流【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii本指南以iii-sdkNode.js/TypeScript 版为核心讲解如何将业务代码注册为可被 iii 引擎实时编排的函数Function、如何通过触发器Trigger把 HTTP、cron、队列等外部事件绑定到函数以及如何使用trigger()以同步、异步enqueue与 fire-and-forget 三种方式发起调用。读完本文你将能够独立完成一个 Worker 的注册、函数/触发器声明、调用与错误处理并理解其背后基于 WebSocket 的协议与重连机制。iii-sdk是 iii 项目的官方 Node.js SDKApache-2.0 许可ESM 模块详见 sdk/packages/node/iii/package.json源码位于 sdk/packages/node/iii/src。它与 sdk/packages/python、sdk/packages/rust 等 SDK 保持接口与行为对齐。安装使用任一包管理器安装即可pnpm add iii-sdk # 或 npm install iii-sdk从 sdk/packages/node/iii/package.json 的exports字段可以看出包除了主入口外还按需导出了./stream、./state、./channel、./trigger、./runtime、./errors、./engine、./protocol、./helpers、./internal等子模块均提供import/require双格式构建产物。其运行时依赖极简iii-dev/helpers本仓库工作区包、opentelemetry/api遥测与wsWebSocket 客户端。快速上手Hello World官方 README 给出的最小示例见 sdk/packages/node/iii/README.md覆盖了“注册函数 → 注册触发器 → 本地调用”的完整闭环import { registerWorker } from iii-sdk const iii registerWorker(ws://localhost:49134) iii.registerFunction(hello::greet, async (input) { return { message: Hello, ${input.name}! } }) iii.registerTrigger({ type: http, function_id: hello::greet, config: { api_path: /greet, http_method: POST }, }) const result await iii.trigger({ function_id: hello::greet, payload: { name: world } })流程可以拆解为四步registerWorker(url)建立与引擎的 WebSocket 连接返回一个IIIClient实例内部为Sdk类见 sdk/packages/node/iii/src/iii.tsregisterFunction(id, handler)把本地异步函数注册为可被按名调用的函数registerTrigger({ type, function_id, config })把外部事件源这里是 HTTP 路径/greet绑定到目标函数事件发生时引擎自动触发调用await iii.trigger({ function_id, payload })主动发起一次同步调用并等待结果。注意registerWorker的构造函数会立刻执行this.connect()iii.ts因此连接是自动建立、无需手动connect的未连接成功前发送的消息会被缓存进messagesToSend队列在onSocketOpen时统一冲刷iii.ts。registerWorker引擎地址解析与初始化选项地址解析优先级registerWorker(address?, options?)的第一个参数是引擎的 WebSocket 地址。从源码 resolveAddress 可以看到严格的解析顺序显式传入的address永远最高优先级环境变量III_URL由拉起 Worker 的编排方设置例如iii compose、容器运行时、systemd兜底默认值DEFAULT_ENGINE_URL ws://127.0.0.1:49134。一个值得注意的细节是默认地址刻意写成 IPv4 回环127.0.0.1而非localhost因为localhost在部分主机上会解析为::1IPv6而引擎可能只监听 IPv4导致连接失败iii.ts。因此本地联调时建议显式使用ws://127.0.0.1:49134或ws://localhost:49134均可但以源码注释为准更稳妥。InitOptions 详解registerWorker的第二个参数options类型为InitOptionsiii.ts常用字段如下字段类型默认值说明workerNamestringhostname:pidWorker 显示名非空的III_WORKER_NAME环境变量会覆盖它编排方分配的标识优先见 resolveWorkerNamenamespacestring无引擎使用defaultWorker 所属命名空间解析顺序为options.namespace→III_NAMESPACE→ undefinedworkerDescriptionstring无一行人类/LLM 可读的 Worker 说明会呈现在engine::workers::list/engine::workers::info中enableMetricsReportingbooleantrue是否通过 OpenTelemetry 上报 Worker 指标invocationTimeoutMsnumber30000worker.trigger()默认调用超时毫秒单次调用可用timeoutMs覆盖reconnectionConfigPartialIIIReconnectionConfig见下表WebSocket 断线重连策略otelOmitOtelConfig, engineWsUrl自动初始化OpenTelemetry 配置{ enabled: false }或环境变量OTEL_ENABLEDfalse/0/no/off可关闭headersRecordstring, string无WebSocket 握手阶段发送的自定义 HTTP 头官方文档示例给出了典型用法const worker registerWorker(ws://localhost:49134, { workerName: my-worker, invocationTimeoutMs: 10000, reconnectionConfig: { maxRetries: 5 }, })命名空间namespace语义命名空间是 iii 中隔离注册与调用范围的关键概念SDK 对其做了非常严谨的处理resolveNamespace解析顺序options.namespace→process.env.III_NAMESPACE→ undefined为 undefined 时引擎应用其default命名空间显式传入空白字符串的 namespace 会直接抛错——声明了命名空间却不给它名字 与 不声明命名空间 含义相反前者会让整个项目静默注册到错误的命名空间且运维者无法从声明中察觉环境变量为空白如III_NAMESPACE${NS}且 NS 未设置则按未设置处理这是 shell 表达未设置变量的惯用方式SDK 尊重这一语义。命名空间不仅作用于注册Worker 及其函数注册在哪个命名空间它后续的trigger调用与registerTrigger绑定就默认跟随哪个命名空间除非调用时显式指定别的。此外有一个专门的处理函数 invocationNamespace引擎内建函数engine::前缀的隐式调用固定落在default命名空间避免把引擎内建泄漏进 Worker 命名空间。重连与心跳连接可靠性SDK 内置了一套与 Rust SDK 对齐的连接可靠性机制常量定义在 sdk/packages/node/iii/src/iii-constants.ts常量默认值含义WS_HANDSHAKE_TIMEOUT_MS10000WebSocket 握手超时WS_PING_INTERVAL_MS20000客户端心跳 ping 间隔WS_IDLE_TIMEOUT_MS60000超过该时长无任何入站帧message/ping/pong则强制断开以触发重连DEFAULT_INVOCATION_TIMEOUT_MS30000调用默认超时重连策略IIIReconnectionConfigiii-constants.ts采用指数退避 抖动字段默认值说明initialDelayMs1000起始延迟毫秒maxDelayMs30000延迟上限backoffMultiplier2指数退避倍数jitterFactor0.3随机抖动因子 0-1maxRetries-1最大重试次数-1表示无限连接状态通过getConnectionState()获取可能的取值iii-constants.ts为disconnected、connecting、connected、reconnecting、failed。其中failed是终态——它只出现在引擎致命拒绝注册之后SDK 不会对该状态继续重连。优雅关闭进程退出时应当调用shutdown()释放资源Sdk.shutdown它会关闭 OpenTelemetry、清除重连与心跳定时器、以Error(iii is shutting down)拒绝所有挂起中的调用、最后关闭 WebSocket。官方建议配合信号处理process.on(SIGTERM, async () { await worker.shutdown() process.exit(0) })注册函数本地处理器与 HTTP 外部函数registerFunction(functionId, handlerOrInvocation, options?)支持两种形态Sdk.registerFunction。形态一本地异步处理器官方 README 示例iii.registerFunction(orders::create, async (input) { return { status_code: 201, body: { id: 123, item: input.body.item } } })处理器类型RemoteFunctionHandler的签名是(data: TInput, metadata?: JsonValue) PromiseTOutputsdk/packages/node/iii/src/types.ts第一个参数是调用负载第二个是可选的逐调用metadata任意 JSON随调用独立于 payload 传输未附加时为undefined。已有的单参数处理器完全兼容多余参数会被忽略。注意几个 SDK 强制的约束functionId为空字符串或纯空白会抛出id is required同一个functionId重复注册会抛出function id already registered: id本地 Map 校验iii.ts返回值是一个FunctionRef含id与unregister()可用于后续注销函数。形态二HTTP 外部函数代理到远端除了本地处理器还可以传入HttpInvocationConfig把函数代理到外部 HTTP 服务如 AWS Lambda、Cloudflare Workers 等引擎侧负责转发调用。字段包括url、method默认POST、timeout_ms、headers、auth如{ type: bearer, token_key: LAMBDA_AUTH_TOKEN }。从 iii.ts 可以看到注册消息中会携带完整的invocation配置块。const lambdaRef worker.registerFunction( external::my-lambda, { url: https://abc123.lambda-url.us-east-1.on.aws, method: POST, timeout_ms: 30_000, auth: { type: bearer, token_key: LAMBDA_AUTH_TOKEN }, }, { description: Proxied Lambda function }, )一个实现细节对于 HTTP 形态注册的函数SDK 不保存本地 handler。若引擎反向路由调用到该函数SDK 会回传错误码function_not_invokableFunction is HTTP-invoked and cannot be invoked locally函数根本不存在则回传function_not_foundonInvokeFunction。注册触发器把外部事件绑定到函数registerTrigger({ type, function_id, config })返回一个带unregister()的Trigger句柄Sdk.registerTrigger。官方 README 示例iii.registerTrigger({ type: http, function_id: orders::create, config: { api_path: /orders, http_method: POST }, })引擎内置的触发器类型包括httpHTTP 路由、cron定时调度配置形如{ expression: 0 */5 * * * * * }、queue队列消费以及durable:subscriber可靠订阅等具体以引擎支持的触发器类型为准。触发器的type决定config的结构。注册时的命名空间语义同样严格iii.ts未显式设置namespace时触发器默认落在本 Worker 的命名空间而非引擎的default。原因是触发器指向一个函数而该函数注册在本 Worker 的命名空间——若默认落到default触发器触发后就会解析不到目标函数。想绑定到其他命名空间包括default需要显式声明。注销触发器const trigger worker.registerTrigger({ type: cron, function_id: my-service::process-batch, config: { expression: 0 */5 * * * * * }, }) // 稍后移除 trigger.unregister()自定义触发器类型registerTriggerType如果内置触发器类型不够用SDK 允许向引擎注册自定义触发器类型扩展外部事件 → 函数调用的映射。registerTriggerType(triggerType, handler)的 handler 需实现registerTrigger/unregisterTrigger两个回调接口定义见 sdk/packages/node/iii/src/triggers.tstype CronConfig { expression: string } worker.registerTriggerTypeCronConfig( { id: cron, description: Fires on a cron schedule }, { async registerTrigger({ id, function_id, config }) { startCronJob(id, config.expression, () worker.trigger({ function_id, payload: {} }), ) }, async unregisterTrigger({ id }) { stopCronJob(id) }, }, )TriggerConfigTConfigtriggers.ts包含id、function_id、config、可选的metadata以及namespace——这个字段由 SDK 在注册时从 Worker 命名空间填充触发方provider后续调用trigger()时必须透传否则可能落到错误的命名空间。registerTriggerType返回的TriggerTypeRefTConfigtypes.ts还提供了三个便捷方法registerTrigger(functionId, config, metadata?)绑定一个该类型的触发器registerFunction(functionId, handler, config, metadata?)注册函数并立即绑定触发器一次调用完成两件事且自动把触发器命名空间默认到 Worker 命名空间避免函数与触发器分离导致解析失败unregister()注销整个触发器类型。调用函数同步、入队与 fire-and-forgettrigger(request)是唯一的调用入口其路由行为由action字段决定。官方文档整理的三种模式如下action行为返回类型不传同步等待函数返回PromiseTOutputTriggerAction.Enqueue({ queue })经具名队列异步路由引擎确认入队PromiseEnqueueResult含messageReceiptIdTriggerAction.Void()fire-and-forget无响应Promiseundefinedimport { registerWorker, TriggerAction } from iii-sdk const iii registerWorker(ws://localhost:49134) // 同步调用等待结果 const result await iii.trigger({ function_id: orders::create, payload: { item: widget } }) // fire-and-forget不等待 iii.trigger({ function_id: analytics::track, payload: { event: page_view }, action: TriggerAction.Void(), }) // 经命名队列异步处理 const { messageReceiptId } await iii.trigger({ function_id: payments::charge, payload: { orderId: 123, amount: 49.99 }, action: TriggerAction.Enqueue({ queue: payment }), })从 Sdk.trigger 的源码看三种模式的实现差异明显Void直接发InvokeFunction消息不生成invocation_id、不注册 pending 调用、不等待响应立即返回undefined同步 / Enqueue生成invocation_idcrypto.randomUUID()注册进invocationsMap 并用effectiveTimeouttimeoutMs ?? invocationTimeoutMs启动超时定时器超时则以InvocationError{ code: TIMEOUT }拒绝每次调用都会注入traceparent/baggageOpenTelemetry 上下文传播供链路追踪使用。TriggerAction构造器本身在 iii.ts 定义并有一组专门的契约测试锁死其线上格式sdk/packages/node/iii/tests/trigger-action.test.tsTriggerAction.Enqueue({ queue: orders })必须序列化为{ type: enqueue, queue: orders }TriggerAction.Void()必须序列化为{ type: void }——这是引擎侧TriggerAction反序列化所依赖的协议约定。关于 Enqueue 的两个前提源码注释明确说明目标队列需要由worker-compose.yaml中的 queue worker 声明queue_configs否则触发会被引擎以enqueue_error无队列提供者拒绝。错误处理与连接诊断SDK 把调用失败统一收口为两个带类型码的Error子类sdk/packages/node/iii/src/errors.tsInvocationErrortrigger()失败时的统一错误类型字段含code、message、function_id、stacktrace。覆盖三类失败调用被拒绝如 RBACFORBIDDEN、handler 层失败引擎回传invocation_failed附带调用栈、超时TIMEOUT。message 统一格式化为${code}: ${message}避免旧版拒绝值打印成[object Object]的问题。未知形状的错误会被包装为code: UNKNOWN见 toInvocationErrorRegistrationRejectedError引擎拒绝 Worker 身份注册时的致命错误字段含code、namespace、worker_name、function_id、owner_worker_id。触发后连接进入终态failed不再重连。注册拒绝registrationrejected的两种典型码iii.ts错误码场景严重性WORKER_NAMESPACE_CONFLICT另一个存活的 Worker 已持有同一(namespace, worker_name)引擎关闭连接致命SDK 停止且不重连FUNCTION_NAMESPACE_CONFLICT同命名空间内另一 Worker 已导出同名函数仅该注册被拒非致命仅告警Worker 继续服务其他函数诊断接口与 Python/Rust SDK 对齐getConnectionState()当前连接状态getAddress()实际解析到的引擎地址getFatalError()致命注册拒绝的RegistrationRejectedError健康时为undefined。API 速查表官方 README 整理的 API 一览完整继承自 sdk/packages/node/iii/README.md操作签名说明初始化registerWorker(url, options?)创建并连接引擎返回ISdk实例注册函数iii.registerFunction(id, handler, options?)注册一个可按名调用的函数注册触发器iii.registerTrigger({ type, function_id, config })把触发器HTTP、cron、queue 等绑定到函数调用等待await iii.trigger({ function_id, payload })调用函数并等待结果调用fire-and-forgetiii.trigger({ function_id, payload, action: TriggerAction.Void() })调用但不等待调用入队iii.trigger({ function_id, payload, action: TriggerAction.Enqueue({ queue }) })经具名队列路由调用源码导读与延伸阅读如果想深入理解 SDK 与引擎的交互推荐按以下顺序阅读本仓库源码sdk/packages/node/iii/src/iii.tsSdk类全部实现——地址/命名空间解析、消息收发、重连与心跳、注册拒绝处理、TriggerAction构造器与registerWorker入口sdk/packages/node/iii/src/iii-constants.ts引擎内建函数路径engine::functions::list、engine::workers::list、engine::workers::register等与所有连接/重连/超时常量sdk/packages/node/iii/src/types.tsIIIClient公共接口、Trigger/FunctionRef/TriggerTypeRef句柄类型、流式请求响应类型sdk/packages/node/iii/src/errors.tsInvocationError与RegistrationRejectedError的定义与线上错误体识别sdk/packages/node/iii/tests/trigger-action.test.tsTriggerAction线上格式契约测试sdk/packages/node/iii/README.md官方 SDK 文档本文的基础。此外SDK 测试目录还覆盖了连接握手超时、心跳、断线重连reattach、命名空间继承、RBAC Worker、流stream、状态state、发布订阅pubsub等大量行为测试见 sdk/packages/node/iii/tests是理解 SDK 边界行为的绝佳参考。包级配置构建、测试、子模块导出可查阅 sdk/packages/node/iii/package.json 与 sdk/packages/node/iii/vitest.config.ts。【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价