本文是专栏「n8n 工作流引擎剖析」第 05 章(组件深度剖析)的第 01/11 篇,承接上一篇《贯穿示例:Ada 的订单接入工作流》。编辑器是一个配角,所以本篇比较短。
你在这里:读完本文,你会知道编辑器做什么、不做什么,它与服务端的哪些接口对话,以及节点的实时进度是怎么传到浏览器的。
缩写:UI(User Interface,用户界面)、REST(Representational State Transfer,表征状态转移)、API(Application Programming Interface,应用程序编程接口)、WS(WebSocket,WebSocket 协议)、SSE(Server-Sent Events,服务器发送事件)、ID(Identifier,标识符)、JSON(JavaScript Object Notation,JavaScript 对象表示法)、HTTP(Hypertext Transfer Protocol,超文本传输协议)、DTO(Data Transfer Object,数据传输对象)。
角色回顾
负责:编写工作流(节点、连接、参数、表达式)、创建凭据、触发手动运行、发布、展示执行记录。
出现于:S1(搭建 + 凭据)、S2(发布)、S12(读取执行记录)。
内部设计
图注:编辑器在本地编辑状态,通过 REST 来持久化或运行,再通过一条推送通道监听实时进度。
- 编辑器编辑的是一份 JSON 文档。它保存的内容正是
IWorkflowBase:nodes和connections(见《n8n 概念地图》)。不存在另一套"编辑器专属格式"。 - 与服务端之间有两条通道。
- REST用于发送命令:
POST /workflows/:id/run(手动执行)、POST /workflows/:id/activate(也就是"发布"按钮——代码里仍然叫activate,界面上写的是"发布")、PATCH /workflows/:id(保存)。 - 推送(WebSocket 或 Server-Sent Events)用于服务端主动发起的事件:
executionStarted、nodeExecuteBefore、nodeExecuteAfter、executionFinished……(frontend/editor-ui/src/app/push-connection/、cli/src/push/websocket.push.ts、sse.push.ts)。
- REST用于发送命令:
pushRef把一个浏览器标签页和它发起的运行绑在一起。编辑器在 REST 调用上带一个push-ref请求头;服务端把它一路带入执行过程,钩子层(本系列后续文章会展开)只会把节点事件推送给这一个标签页。- 手动运行受到限制,且以数据库为准。
WorkflowsController.runManually(cli/src/workflows/workflows.controller.ts第 506 行)总是从数据库加载已存储的工作流——注释里写明这是为了"防止执行任意的工作流定义"——然后调用WorkflowExecutionService.executeManually(workflow-execution.service.ts第 344 行),它会把工作流标记为测试用的非活动状态,决定是部分执行还是完整执行,并且如果起始触发器是 webhook,还会注册一个测试 webhook(TestWebhooks,路径前缀webhook-test),等待一次调用。 - 发布需要特定权限范围。激活路由上挂着
@ProjectScope('workflow:publish'),外加一次协作写锁检查(collaborationService.validateWriteLock),防止两个人同时编辑互相覆盖。请求体中带有versionId和expectedChecksum。
交互关系
| 方向 | 契约 |
|---|---|
| 编辑器 → 服务端 | 会话 Cookie +push-ref请求头;JSON 请求体由 DTO(数据传输对象)校验(ManualRunDto、ActivateWorkflowDto) |
| 服务端 → 编辑器 | 带类型的推送消息(PushMessage),投递给指定的pushRef |
| 编辑器 ↔ 凭据 | 发送凭据的字段去创建/更新;读取时绝不返回明文(凭据加解密是本系列后续文章的主题) |
⚓ 回到示例
S1。Ada 的画布变化实时存在浏览器状态仓库里。她保存时,PATCH /workflows/:id会发送{ nodes, connections, … }。她创建 “Billing API key” 时,凭据字段会发到凭据接口,并在服务端完成加密(S10 会展示解密过程)。
S2。点击发布会发送:
POST /rest/workflows/<workflowId>/activate push-ref: <标签页 id> Content-Type: application/json { "versionId": "<uuid>", "expectedChecksum": "<hash>" }控制器校验写锁,调用workflowService.activateWorkflow(...),最终落到ActiveWorkflowManager.add(...)——接下来交给触发器注册中心接手(下一篇详细展开)。
S12。打开执行记录页面就是一次对已存储数据的 REST 读取(生产环境的运行不带pushRef,所以没有任何实时推送)。
rest是默认的 REST 接口前缀(@n8n/config/.../endpoints.config.ts)。
失败行为
| 失败情形 | 行为 |
|---|---|
| 推送连接断开 | 编辑器会自动重连(useReconnectTimer、useHeartbeat);事件携带一个按运行计次的sequenceNumber,让迟到/乱序的事件不会渲染出错误的"当前正在执行"节点 |
| 两个人同时编辑同一个工作流 | 发布时做写锁校验;expectedChecksum能检测出过期的副本 |
| 测试 webhook 始终没被调用 | 测试 webhook 的注册是临时的(cli/src/constants.ts中TEST_WEBHOOK_TIMEOUT= 2 分钟);生产环境的 webhook 是独立的数据库记录 |
下一篇:《触发器注册中心 Trigger Registry》,讲清楚"发布"在服务端到底做了什么。
📚 返回专栏目录