前端开发
用 Inngest 构建可持久化、自动重试、可调度…
当需要构建能跨进程崩溃恢复、失败自动重试、按计划运行、响应事件或跨基础设施故障保持状态的函数时使用(如 webhook 处理、易失败的 cron、后台任务、可断点续跑的工作流)。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
用 Inngest 构建可持久化、自动重特定
解决思路
- 将每个副作用和非确定性代码封装进 step.run():API 调用、网络请求、数据库读写、文件 I/O、任何非确定性操作、任何希望独立重试的操作都必须放入 step;纯计算、数据转换、简单校验、无副作用的确定性操作、日志不要放入 step。
- 把非确定性逻辑(如 Date.now())放进 step 内部,避免在函数体顶层执行导致多次运行。
- 遵守函数硬限制:每次运行最多 1000 个 step,每个 step 返回数据最多 4MB,函数运行状态(含事件数据、step 输出、函数输出)合计最多 32MB,每个 step 约 50-100ms HTTP 开销;超限时用 step.invoke() 或 step.sendEvent() 拆分成更小的函数。
- 用 inngest.createFunction 创建函数:设置唯一且永不更改的 id、triggers 数组、retries(默认每 step 4 次重试)、concurrency(最大并发)。
- 配置触发器:单个事件 { event: "..." }、带条件过滤 { event: "...", if: '...' }、多个触发器(最多 10 个)、cron 表达式(如 "0 9 * * *")、带时区 cron(如 "TZ=Europe/Paris 0 12 * * 5"),可混合事件与 cron。
- 用 step.invoke("id", { function, data }) 调用其他函数并消费其返回值。
- 用 step.run 的 step ID 实现记忆化:ID 可复用(Inngest 自动计数),但应使用描述性 ID(如 validate-payment、charge-customer、send-confirmation),部署后不要更改 step ID。
- 生产者侧幂等:在 inngest.send 中传入自定义 id(如 `checkout-completed-${cartId}`)实现 24 小时去重。
- 消费者侧幂等:在 createFunction 中设置 idempotency 表达式(如 "event.data.cartId" 或 'event.data.userId + "-" + event.data.organizationId')避免重复执行。
- 用 cancelOn 实现事件取消:配置 { event: "...", if: "event.data.orderId == async.data.orderId" },其中 event 指原始触发事件、async 指新匹配事件。
- 用 timeouts 配置超时取消:{ start: "5m", finish: "30m" }。
- 监听 inngest/function.cancelled 事件并检查 event.data.function_id,在 step 中执行清理逻辑(如 cleanupOrderResources(event.data.run_id))。
- 理解默认重试:每个 step 共 5 次尝试(1 次初始 + 4 次重试),指数退避加抖动,每个 step 独立计数;可通过 retries 自定义重试次数。
- 用 attempt 参数(函数级、0 起始、跟踪当前 step 的重试)在重试时切换逻辑。
- 对不会因重试成功的错误抛出 NonRetriableError(如用户不存在)以停止重试。
- 对限流等场景抛出 RetryAfterError("Rate limited", `${retryAfter}s`) 指定重试延迟。
- 日志配置:用 winston 等自定义 logger 并通过 logger 选项传给 Inngest 客户端,或用内置 ConsoleLogger({ level: "debug" })。注意 v4 已移除 logLevel 选项,改用 logger。
- 日志只在 step 内部记录以避免重复,不要在 step 外记录日志。
- 性能优化:v4 默认启用 checkpointing;对 serverless 平台设置 checkpointing.maxRuntime 为平台超时的 60-80%(如 60s 超时设 "50s");需要时用 checkpointing: false 禁用。
- 条件执行 step:根据前一步结果(如 userData.isPremium)决定是否执行某些 step,公共 step 始终执行。
- 错误恢复:用 try/catch 包裹主服务 step,失败时回退到备用服务 step。
- 避免常见错误:非确定性代码在 step 外、数据库调用在 step 外、日志在 step 外、部署后更改 step ID、未处理 NonRetriableError、关键函数忽略幂等。
适用边界 · 注意事项
- 纯计算、数据转换、简单校验、无副作用的确定性操作不需要放入 step。
- 日志不要放在 step 外,否则会重复记录。
- 不要更改已部署函数的 step ID,否则会破坏记忆化。