工作流跑挂了怎么办:Mastra 错误处理与自动重试完全指南
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
Mastra 工作流最常见的死法不是逻辑写错,而是第 3 步调外部 API 时网络抖了一下:超时、报错,整条 run 直接判failed,前面两步的结果白白丢弃,只能从头再跑。这就是工作流错误处理要解决的核心问题——别让一次偶发抖动毁掉一次完整执行。Mastra 的做法是两层自动重试加一套失败定位手段:步骤失败后按配置自动重跑,重试仍失败再通过状态检查、回调和追踪数据把问题钉死在具体的那一步上。
一个步骤超时,为什么整条流程都报废
先看一个典型场景:一条订单处理工作流,fetch-price→validate-stock→call-payment→write-order四个步骤串行。前两步各花了 200 毫秒,第三步调支付网关时碰上 3 秒超时,抛出异常。
问题出在两点。一是没有重试:网络超时是典型的瞬时故障(transient failure),一秒后大概率就好了,但流程没有机会试第二次。二是失败不可见:如果你只是await run.start()然后直接拿result,不注意看status字段,代码会一直以为流程成功了。
Mastra 工作流的设计是把这两件事分开处理:偶发故障交给重试机制自动兜底,真正的失败靠结果状态和追踪数据来定位。下面是具体配置。
Mastra 重试策略怎么配:两层兜底
Mastra 的重试分两级:工作流级retryConfig给所有步骤设默认值,步骤级retries给个别"玻璃心"步骤单独加码。两级只配一级也能用,但推荐的组合是"工作流级保底 + 高风险步骤单独覆盖"。
import { createWorkflow, createStep } from '@mastra/core/workflows' const fetchStep = createStep({ id: 'fetch-data', execute: async ({ inputData }) => requestExternalAPI(inputData), retries: 3, // 单步覆盖:这个易超时的步骤最多试 3 次 }) export const orderWorkflow = createWorkflow({ id: 'order-workflow', retryConfig: { attempts: 5, delay: 2000 }, // 工作流级默认值 }) .then(fetchStep) .commit()工作流级 retryConfig:给所有步骤一个默认值
retryConfig有两个字段:
attempts:单个步骤失败后最多重试几次,上例是 5 次;delay:每次重试前等待的毫秒数,上例是 2000 毫秒,也就是固定间隔。
不配置时默认不重试(attempts 为 0),步骤一挂流程就挂。所以哪怕你觉得"我们的 API 很稳定",也建议至少给一个全局默认值——网络抖动不看场合,稳定与否只体现在概率上。
步骤级 retries 与固定间隔 vs 指数退避
retries写在createStep里,只对该步骤生效,并覆盖工作流级的attempts。判断标准很简单:这一步调的是不是外部依赖?调远程服务、数据库、第三方接口的步骤值得重试;纯本地计算、数据校验的步骤重试多少次结果都一样,配了也是浪费。
关于延迟策略要说明一点:delay是固定间隔,每次重试前都等同样的毫秒数。如果你需要指数退避(第 1 次等 1 秒、第 2 次等 2 秒、第 3 次等 4 秒……),目前可以在步骤的execute内部自己包一层递增等待,或者把这类任务交给带退避能力的外部任务队列。对大多数场景,固定间隔 2~5 秒已经够用,别一上来就把退避逻辑复杂化。
错误分类:哪些该重试,哪些该直接走兜底
重试不是万能药。盲目把所有错误都重试,会把"本来就不该再试一次"的失败放大成多次副作用——比如重复扣款。按错误类型区分对待:
| 错误类型 | 典型表现 | 该不该重试 | 处理建议 |
|---|---|---|---|
| 网络类 | API 超时、连接中断、5xx 响应 | 该 | 配retries/retryConfig,自动兜底 |
| 业务逻辑类 | 数据校验失败、余额不足、条件不满足 | 不该 | 在步骤内catch后返回错误状态,用.branch()路由到降级步骤 |
| 资源类 | 内存不足、并发打满、限流 429 | 视情况 | 先降并发再重试;对限流按返回的建议等待时间延后 |
关键技巧在业务类错误上:Mastra 的重试对"步骤抛异常"一视同仁,它不会帮你区分错误类型。所以正确的姿势是在步骤内部把不可重试的错误消化掉——try/catch捕获后return { status: 'error' },然后在流程上用.branch()按status分流:正常的走主路径,异常的走降级路径。这样重试只留给真正的瞬时故障,业务错误走的是你设计的兜底分支,两者互不干扰。
工作流失败怎么定位:状态检查、onError 与追踪
重试耗尽之后,你要知道"挂在哪一步、为什么挂"。三个工具按排查深度递进:
- 检查结果对象。
run.start()返回的result里有status(success/failed/suspended/tripwire)和steps,遍历result.steps就能找到status === 'failed'的那个步骤及其error详情。这是最低成本的动作,很多"工作流挂了"的问题查到这一步就有答案。 - 挂
onError回调。在createWorkflow的options里配置,流程失败(failed或tripwire)时触发,收到错误详情、各步骤结果、runId、workflowId。适合接告警:失败即通知值班群或写进错误追踪服务。注意回调里抛出的异常会被框架捕获并记日志,不会反过来影响流程结果,可以放心在里面调外部服务。 - 看追踪与快照。流程的每次运行都会把 Traces(链路追踪)和 Snapshots(步骤快照)写入 Mastra Storage,配合可观测性能力可以回看整条执行链路,确认失败步骤之前的数据是否正常。
另外,长流程建议用run.stream()替代一次性await:它以流的方式逐步吐出执行统计,你能实时看到流程推进到哪一步,而不是等几十秒后才发现它早就失败了。更多细节可查 工作流错误处理官方文档 和 可观测性追踪文档。
避坑清单:重试策略的实战建议
把上面的机制组合起来,再对照这几条实战经验,基本能覆盖绝大多数"工作流跑挂了"的现场:
- ⚠️ 先确认幂等再开重试。扣款、发通知这类步骤重试一次就是一次真实副作用,这类步骤要么不配重试,要么在内部做去重(记录已处理的外部单号)。
- 重试次数别贪多。3~5 次足够扛过绝大多数瞬时故障,超过 5 次大概率说明对方服务真的挂了,重试只是把报错时间往后拖。
delay别设成 0。给上游服务一点喘息窗口,同时也避免你的实例在故障期间疯狂打对面接口、加剧雪崩。- 业务错误不要裸抛。凡是"重试也没用"的错误(校验失败、状态不满足),在步骤内捕获并转成结构化状态,走
.branch()降级路径。 - 给失败留后路。
onError接告警 + 追踪数据落盘,让你能在重试耗尽后 5 分钟内定位到具体步骤,而不是第二天靠回忆复现。 - 定期看重试率。如果某一步的重试比例长期偏高(比如 10% 以上),那不是该加
retries,而是该检查这个外部依赖或自己的超时设置。
把retryConfig加上、onError接上告警、失败时先看result.steps再下结论——这三件事做完,你的工作流就已经从"挂了靠运气"变成"挂了能自愈、不能自愈也能快速定位"的状态。
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考