05.04 · n8n 源码剖析:工作流运行器 Workflow Runner
本文是专栏「n8n 工作流引擎剖析」第 05 章组件深度剖析的第 04/11 篇承接上一篇《Webhook 接入层 Webhook Ingress》。核心是WorkflowRunner与ActiveExecutions。你在这里读完本文你会知道一次执行是如何被创建出来的、n8n 如何决定它在哪里运行以及围绕着一次正在运行的执行有哪些簿记工作超时、取消、响应 Promise。缩写DBDatabase数据库、IDIdentifier标识符、HTTPHypertext Transfer Protocol超文本传输协议、JSONJavaScript Object NotationJavaScript 对象表示法。角色回顾负责把用这些首批数据项运行这个工作流变成一条持久化的执行记录和一次正在进行中的运行——可以在本地跑也可以经由队列跑。掌握执行 ID、设置超时时间、正在等待的 HTTP 调用方的响应 Promise、取消句柄。不做不知道节点内部如何工作不在节点之间搬运数据。出现于S5 → S6以及每一次手动运行、每一次由触发器发起的运行。内部设计cli/src/下两个相互协作的类类文件角色WorkflowRunnerworkflow-runner.ts编排的配方run、runMainProcess、enqueueExecutionActiveExecutionsactive-executions.ts正在运行的执行的内存登记表创建数据库记录add持有PCancelable句柄、响应 Promise以及执行后置PromiseWorkflowRunner.run()第 407 行是否拒绝通过是否run(data, loadStaticData, realtime, existingExecution, responsePromise)是否走 engine v2engineV2Dispatcher.start超出本文范围establishContextForPersistencecredentialsPermissionChecker.check(workflow nodes)activeExecutions.add failExecution→ 返回 idprepareNewExecution → WorkflowactiveExecutions.add→ 执行记录状态 new绑定响应 Promise启动流式心跳executions.mode queue且非 manualenqueueExecution→ Bull 任务runMainProcess→ 进程内运行WorkflowExecute执行后置 Promise图注运行器是一棵决策树最终走到两条运行路径之一无论走哪条都会返回一个执行 ID。持久化上下文establishContextForPersistence和凭据访问检查credentialsPermissionChecker.check排在最前面——如果一个工作流引用了当前执行方所在项目无权使用的凭据它会作为一次执行而失败因而在历史记录里可见而不是直接把请求丢弃。prepareNewExecution构建Workflow对象在手动/评估模式下会解析出 pin data。ActiveExecutions.add第 71 行通过executionPersistence.create({ data, mode, finished:false, workflowData, status:new, workflowId, … })插入记录——此时整个IRunExecutionData包括预先填好的nodeExecutionStack就已经存进去了——并预留并发容量ConcurrencyCapacityReservationevaluation模式下跳过。在常规模式下会立即执行setRunning。决定在哪里运行。constshouldEnqueueOFFLOAD_MANUAL_EXECUTIONS_TO_WORKERStrue?modequeue:modequeuedata.executionMode!manual;所以在队列模式下生产运行会进工作进程手动编辑器运行留在主进程除非某个环境变量开关另有规定。runMainProcess第 569 行设置一个软超时workflowSettings.executionTimeout或全局默认值上限由maxTimeout决定构建带执行超时时间戳的additionalData调用setRunning(executionId)组装生命周期钩子getLifecycleHooksForRegularMain加上sendResponse解析 HTTP 响应 Promise和sendChunk流式输出两个处理器然后调用new WorkflowExecute(additionalData, mode, data.executionData).processRunExecutionData(workflow)——一个PCancelableIRun——并把它挂到登记表上。完成时调用finalizeExecution(executionId, fullRunData)。enqueueExecution第 740 行→ 见下一篇《伸缩队列 Scaling Queue》。超时是软的。计时器触发时stopExecution(id, TimeoutExecutionCancelledError)会在当前节点跑完之后才取消——引擎会在节点之间检查shouldStopExecuting()。ActiveExecutions的职责方法用途add第 71 行创建记录或续接一条已存在的等待中记录、预留容量、返回 idattachWorkflowExecution第 199 行存下可取消的 Promise这样stopExecution才能取消它attachResponsePromise/resolveResponsePromise连通到在lastNode/responseNode模式下等待中的 HTTP 调用方stopExecution第 225 行以一个带类型的ExecutionCancelledError取消手动、超时、关闭finalizeExecution第 255 行解析执行后置 Promise、释放容量、从登记表中移除getPostExecutePromise第 295 行让调用方可以等待完成供lastNode模式和子工作流使用交互关系对象契约Webhook 接入层、触发器、编辑器手动运行、子工作流节点调用run(IWorkflowExecutionDataProcess, …)得到一个执行 ID引擎本系列后续文章构造WorkflowExecute收到IRun伸缩队列下一篇调用addJob监听任务消息钩子本系列后续文章根据当前进程角色选用哪一套钩子并发控制容量预留可能在执行开始前就先把它延后⚓ 回到示例 —— S5 → S6接入层调用run(...)带上executionMode: webhook、包含预填好的栈Order Webhook 该数据项的executionDataworkflowData 已发布版本。credentialsPermissionChecker.check(wf123, nodes)——httpHeaderAuth凭据cred42属于 Ada 的项目 → 通过。ActiveExecutions.add插入execution_entity状态new模式webhook及其execution_data负载假设 id 为1042。队列模式且模式 ≠manual→enqueueExecution(1042, wf123, data, loadStaticDatafalse, realtimefalse, …)。realtime为假因为onReceived会延迟回复!didSendResponse !shouldDeferOnReceivedResponse→false所以任务优先级是100而不是50。run返回1042接入层发出此前延迟的200 {message:Workflow was started}。在常规模式下同样的调用会直接走到runMainProcessS7–S12 会在这个进程里原地发生。失败行为失败情形结果凭据访问被拒绝创建执行记录并立即失败failExecution返回 id在历史记录中可见无法建立持久化上下文同上——是一次失败的执行而不是一个直接抛出的 HTTP 错误enqueueExecution抛出异常Redis 挂了用工作进程式的钩子跑一遍processError让执行以error结束然后重新抛出异常超时软取消引擎会在下一次循环迭代时注意到shouldStopExecuting把运行标记为canceled结果中带有一个TimeoutExecutionCancelledError关闭对正在运行的执行抛出SystemShutdownExecutionCancelledError执行后置 Promise 被拒绝记录日志并上报取消类错误会被忽略下一篇《伸缩队列 Scaling Queue队列模式》讲清楚任务是怎么从主进程搬到工作进程的。 返回专栏目录

相关新闻

中职生的真实日常:谁说我们没未来?

中职生的真实日常:谁说我们没未来?

写在前面:我是一名中职在读生,学的是护理专业。这篇文章不卖惨、不鸡汤,就是想用我自己和身边同学的真实经历,聊聊中职生到底在过什么样的日子,以及我们是怎么一步步找到出路的。一、被误解的我们“你考不上高中才去的…

2026/10/11 4:36:17 阅读更多 →
EG2113D 高压半桥驱动芯片:高压功率变换的实用驱动方案

EG2113D 高压半桥驱动芯片:高压功率变换的实用驱动方案

芯片核心性能特点 EG2113D 专为 N 沟道 MOS 管、IGBT 管栅极驱动设计,采用高端悬浮自举电源架构,高端耐压最高可达 600V,能够适配绝大多数民用高压功率变换电路。芯片最大支持 500kHz 开关频率,兼顾逆变电源、高压 D 类功放对高频…

2026/10/11 4:36:17 阅读更多 →
基于stm32 的OTA在线升级学习笔记(1)

基于stm32 的OTA在线升级学习笔记(1)

OTA升级指的是。。。 现在网络上很多教程都把原理讲的很明白了,但是我自己学的时候没有找到很详细的步骤从0开始一步一步完成双区OTA升级的实验过程,因此我把我的学习过程记录下面供和我一样的小白参考。 原理我这里就不细说了,相信来了解这…

2026/10/11 4:36:17 阅读更多 →

最新新闻

高通CAMX NCS服务架构、初始化时序与踩坑指南

高通CAMX NCS服务架构、初始化时序与踩坑指南

最近在梳理高通Camx功能feature时,又把NCS服务这条主线翻了出来。很多人学CAMX,开口就是Pipeline、Node、Port,以为把这三个概念吃透就等于懂CAMX了。可一旦真去分析代码执行流,或者遇到Session申请不到节点、Flush命令卡住、多摄…

2026/10/11 5:19:39 阅读更多 →
死磕muduo网络库:从Reactor模式到多线程高并发服务端编程

死磕muduo网络库:从Reactor模式到多线程高并发服务端编程

1. 为什么我在学完基础C之后,转头死磕muduo网络库先聊点实在的。我学C大概用了两年多,语法、STL、智能指针、模板这些都能写,但一直有个说不出的憋屈感:写出来的程序好像只会“算数”,不会“干活”。直到我开始接触网络…

2026/10/11 5:19:39 阅读更多 →
泛微查询文档默认显示全部:改造思路与避坑指南

泛微查询文档默认显示全部:改造思路与避坑指南

你把知识管理查询文档改成默认显示全部之后,业务部门的第一反应大概率是“哦,可以了”,只有负责维护泛微系统的人才知道这件事没那么简单。最近我刚处理完一单这样的改造,需求描述就一句话:“知识管理-查询文档页面&am…

2026/10/11 5:19:39 阅读更多 →
训练营打卡全攻略:从目标设定到复盘迁移的完整执行框架

训练营打卡全攻略:从目标设定到复盘迁移的完整执行框架

1. 训练营打卡到底在练什么?先搞懂这套模式的设计逻辑1月25日那一期训练营,我给自己定了个规矩:不请假、不补卡、不发“打卡失败”的丧气话。每天睡前把当天的完成情况如实写下来,配上必要的数据,发到群里就算交作业。…

2026/10/11 5:19:39 阅读更多 →
个人微信API二次开发:如何处理并发请求导致的数据重复?

个人微信API二次开发:如何处理并发请求导致的数据重复?

在微信自动化项目中,有一种问题不太容易发现:同一份数据被处理了两次。例如,两条请求几乎同时到达,都判断某个客户还没有入库,随后分别执行新增操作,最终数据库出现两条重复记录。这类问题通常不是简单的查…

2026/10/11 5:19:38 阅读更多 →
动力总成悬置解耦计算与优化程序:原理、实现与实战避坑

动力总成悬置解耦计算与优化程序:原理、实现与实战避坑

做动力总成悬置解耦计算,最魔幻的事情不是算法写不出来,而是算出来不好用。某天同事跑过来跟我吐槽,说按书上能量解耦法做了个优化程序,解耦率都调到95%以上了,样车一上台架,怠速方向盘还是抖得不行。我第一个问题就问他:你优化里用的刚度是10Hz动刚度还是静刚度?橡胶主簧的安…

2026/10/11 5:18:38 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →