Inngest Steps 是 Inngest 中用于构建健壮、持久工作流的步骤方法。每个步骤都是一个独立的 HTTP 请求,可以独立重试和监控。以下内容主要聚焦 TypeScript;Python 或 Go 请参考 Inngest 文档获取对应语言的指引,核心概念跨语言通用。
核心概念 每一步都会从头重新运行整个函数。必须把所有非确定性代码(API 调用、数据库查询、随机性)放在步骤内,绝不能放在步骤外。每个函数最多 1000 个步骤和 4MB 总步骤数据。正确示例中,所有日志都包在 step.run 内,因此各只执行一次;错误示例中,步骤外的 console.log 会随每个步骤重复执行。
step.run() 将可重试代码作为步骤执行。步骤 ID 可以复用,Inngest 会自动处理计数器。基本用法是传入步骤名和异步或同步函数,返回值可供后续步骤使用;副作用操作无需返回值。建议:把所有非确定性逻辑放入步骤、返回对后续步骤有用的数据、在循环中复用步骤 ID;避免:把确定性逻辑无谓地放入步骤、忘记每个步骤是独立 HTTP 请求。
step.sleep() 暂停执行而不消耗计算时间。支持时长字符串,如 "24h"、"30s"、"7d"。可用于在发送欢迎邮件后等待 3 天再发送跟进邮件等流程。
step.sleepUntil() 暂停到指定日期时间。可传入具体 Date 对象,也可从事件数据中读取时间。
step.waitForEvent() 仅捕获该步骤执行之后发送的事件:在此之前发送的事件不会被捕获。始终检查返回值是否为 null(表示超时、事件从未到达)。用法支持简单匹配(如 match: "data.invoiceId")和基于 CEL 语法的表达式匹配(使用 event 表示原始触发事件,async 表示正在匹配的新事件)。建议:使用唯一 ID 匹配、设置合理超时、处理 null 超时分支、结合 Realtime 实现人工介入流程;避免:期望捕获步骤之前发送的事件、在生产环境不设超时。
step.waitForSignal() 等待唯一信号(而非事件),更适合 1:1 匹配。需要提供信号标识、超时和 onConflict 选项("replace" 覆盖待处理信号,"fail" 抛出错误)。选择建议:waitForEvent 适合多个函数可能处理同一事件的情况;waitForSignal 适合精确到特定函数运行的 1:1 信号。
step.sendEvent() 向其他函数扇出事件而不等待结果。支持发送单个或多个事件。适用于需要触发其他函数、但当前函数不需要其结果的场景。
step.invoke() 调用其他函数并处理其结果,适合函数组合。可以调用其他 Inngest 函数并获取完全类型化的返回值。适用于把复杂工作流拆分为可组合函数、跨工作流复用逻辑、map-reduce 模式。
常用模式 循环与步骤:在循环中复用同一步骤 ID(如 "fetch-page"),Inngest 自动处理计数器,可配合游标实现分页拉取。 并行执行:先创建步骤(不 await),再用 Promise.all 并行执行;大量并行步骤时可启用 optimizeParallelism(据资料约减少 50% HTTP 请求)。 分块任务:将大批量数据分块,每块作为一个步骤并行处理,最后合并结果。
常见注意事项 函数会重新执行:步骤外的代码会在每次步骤执行时运行。事件时序:waitForEvent 只捕获步骤运行之后发送的事件。步骤限制:每函数最多 1000 个步骤、每个步骤输出 4MB、每次函数运行总计 32MB。HTTP 请求:使用 serve 时可通过 checkpointing 减少 HTTP 请求。步骤 ID:循环中可复用,计数器自动处理。并行:使用 Promise.all,步骤多时考虑 optimizeParallelism。
典型使用场景 人工介入流程(waitForEvent + Realtime UI)、多步骤引导(步骤间 sleep、等待用户动作事件)、数据处理(并行步骤处理分块工作)、外部集成(step.run 实现可靠 API 调用)、AI 工作流(step.ai 实现持久化 LLM 编排)、函数组合(step.invoke 构建复杂工作流)。关于收费、价格、平台支持等细节,资料中暂未提供。