news 2026/9/24 16:58:35

agenda-rest 使用指南:为 Node.js 任务调度器 Agenda 构建 REST API 管理服务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
agenda-rest 使用指南:为 Node.js 任务调度器 Agenda 构建 REST API 管理服务

【免费下载链接】agenda

Lightweight job scheduling for Node.js

项目地址:https://gitcode.com/gh_mirrors/ag/agenda
点击查看免费下载

agenda-rest 是 Agenda 生态中一个轻量级 REST API 服务,用于通过 HTTP 接口定义、调度和管理 Agenda 任务(Job)。本文将以 packages/agenda-rest/README.md 为核心,结合该包源码与测试,完整讲解如何从仓库启动服务、以编程方式挂载createServer()、配置X-API-Key认证,以及逐一使用 9 个 REST 端点完成任务定义、一次性调度、周期调度与取消操作,并深入剖析其底层调用链与错误约定。

一、agenda-rest 是什么

agenda-rest对外暴露了一个小巧的 Koa 应用,提供如下能力:

  • 定义任务(Job Definition):通过POST /api/job注册一个任务,可携带 webhook 地址,任务触发时自动向该地址发起 HTTP 请求;
  • 调度一次性任务:立即执行(now)或在指定时间执行(once);
  • 调度周期任务:按固定间隔重复执行(every);
  • 取消任务:按任务名或数据条件批量取消;
  • 健康检查GET /api/health无需认证即可探测服务存活。

它既可以作为独立 CLI 服务在仓库中直接启动,也可以作为中间件/应用被createServer()以编程方式挂载到任意 Node.js 服务中,这与 README 中的定位完全一致(见 packages/agenda-rest/README.md 开头说明)。

从依赖结构看,该包基于 Koa 生态构建:koakoa-routerkoa-bodyparser负责 HTTP 层,commander负责 CLI 参数解析,agenda@agendajs/mongo-backend提供任务调度与 MongoDB 持久化能力(见 package.json 的dependencies字段)。

二、环境要求

运行 agenda-rest 需要满足:

依赖说明
Node.js 18 或更高版本源码与engines字段均要求>=18.0.0(见 package.json)
MongoDB 数据库CLI 服务器模式通过 MongoBackend 连接 MongoDB 持久化任务
Agenda 实例使用createServer()编程方式挂载时,必须传入一个已初始化的 Agenda 实例

三、从仓库运行与 CLI 选项

3.1 安装、构建与启动

在仓库根目录依次执行:

pnpm install pnpm --filter agenda-rest build pnpm --filter agenda-rest start -- --uri mongodb://localhost:27017/agenda

服务默认监听4040端口,所有路由挂载在/api前缀下。构建产物输出到dist/,CLI 入口由 bin/agenda-rest.js 指向dist/cli.js

3.2 CLI 选项

pnpm --filter agenda-rest start -- \ --uri mongodb://localhost:27017/agenda \ --collection agendaJobs \ --port 4040 \ --api-key secret-key
选项默认值说明
--urimongodb://localhost:27017/agendaMongoDB 连接 URI
--collectionagendaJobsAgenda 使用的 MongoDB 集合名
--port4040HTTP 服务监听端口
--api-key配置后启用X-API-Key认证
--timeout5000请求超时时间(毫秒)

这些选项在 cli.ts 中通过commander定义,同时支持短参数别名:-u-c-p-k-t

3.3 CLI 启动流程(源码视角)

从 cli.ts 的.action()实现可以看到完整启动链路:

  1. 解析porttimeout为整数;
  2. 创建new Agenda({ backend: new MongoBackend({ address, collection }) })
  3. await agenda.ready等待 MongoDB 连接就绪;
  4. await agenda.start()启动任务处理器(JobProcessor);
  5. 调用createServer({ agenda, apiKey, timeout })得到 Koa 应用;
  6. app.listen(port)开始监听,并在控制台打印全部端点清单;
  7. 注册SIGTERM/SIGINT处理,实现优雅关闭(先server.close()await agenda.stop())。

四、编程方式使用(createServer)

如果要在现有 Node.js 服务中嵌入 REST API,不需要 CLI,直接调用createServer()

import { Agenda } from 'agenda'; import { MongoBackend } from '@agendajs/mongo-backend'; import { createServer } from 'agenda-rest'; const agenda = new Agenda({ backend: new MongoBackend({ address: 'mongodb://localhost:27017/agenda', collection: 'agendaJobs' }) }); await agenda.ready; await agenda.start(); const app = createServer({ agenda, apiKey: 'secret-key' }); app.listen(4040, () => { console.log('agenda-rest listening on http://localhost:4040'); });

createServer返回的是一个标准 Koa 实例(app.callback()可直接交给 Node HTTP 服务器或 Express 等框架托管),其配置类型AgendaRestConfig定义在 types.ts:

配置项类型说明
agendaAgenda要操作的 Agenda 实例(必填,缺省会直接抛错)
mongoUristringMongoDB 连接 URI(CLI 内部使用)
dbNamestring数据库名
collectionstring任务集合名
apiKeystringAPI 密钥,用于X-API-Key认证
timeoutnumber请求超时(毫秒)
portnumber监听端口(CLI 模式使用)

在 server.ts 中,若未传入agendacreateServer会直接抛出Agenda instance is required,这也是测试套件统一以{ agenda }构造应用的原因(见 api.test.ts)。

五、认证机制

配置apiKey后,除健康检查外的所有端点都要求请求头携带X-API-Key

curl -H "X-API-Key: secret-key" http://localhost:4040/api/job

其实现位于 server.ts 的authenticate中间件:当apiKey存在且请求头x-api-key不匹配时,直接返回403{ error: 'Forbidden: Invalid API key' }。测试用例覆盖了三种场景:无密钥请求返回 403、错误密钥返回 403、正确密钥放行(见 api.test.ts)。

注意两点:

  • GET /api/health未挂载authenticate,因此无需认证即可访问(server.ts);
  • apiKey未配置,authenticate直接放行所有请求——生产环境务必配置密钥或在前置网关层做防护。

六、端点详解

所有端点均位于/api前缀下,请求体由koa-bodyparser解析为 JSON。以下结合 server.ts 的实现逐一说明。

6.1GET /api/health— 健康检查

返回服务健康状态,无需认证:

{ "status": "ok" }

对应测试断言res.body.status === 'ok'(见 api.test.ts)。

6.2GET /api/job— 列出任务定义

返回通过 REST API 创建的内存态任务定义列表(注意:这里列出的是定义而非数据库中的任务实例):

curl -H "X-API-Key: secret-key" http://localhost:4040/api/job

响应形如{ "jobs": [ { "name": "...", "url": "...", "method": "..." } ] }(响应结构见 types.ts)。实现上,定义存放在createServer内部的Map<string, StoredJobDefinition>中(server.ts),因此重启进程后定义会丢失,但已调度进 MongoDB 的任务实例不会丢失。

6.3POST /api/job— 创建任务定义

curl -X POST http://localhost:4040/api/job \ -H "Content-Type: application/json" \ -H "X-API-Key: secret-key" \ -d '{ "name": "send-report", "url": "https://example.com/jobs/send-report", "method": "POST", "headers": { "Authorization": "Bearer token" }, "body": { "report": "daily" } }'

请求体类型为JobDefinitionRequest(types.ts),支持字段:

字段类型说明
namestring任务名(必填)
urlstring任务执行时请求的 webhook 地址
methodstringHTTP 方法,默认POST
headersRecord<string, string>请求头,会自动合并Content-Type: application/json
bodyunknown默认请求体
callback{ url, method?, headers? }可选回调 webhook,任务执行完成后上报结果

校验规则与状态码(均与测试一一对应):

  • 缺少name:返回400 { error: 'Job name is required' }
  • 同名定义已存在:返回409 { error: 'Job "xxx" already exists' }
  • 创建成功:返回200 { success: true, message: 'Job "xxx" created' }

6.4PUT /api/job/:jobName— 更新任务定义

curl -X PUT http://localhost:4040/api/job/send-report \ -H "Content-Type: application/json" \ -H "X-API-Key: secret-key" \ -d '{ "url": "https://example.com/jobs/send-daily-report" }'

请求体是JobDefinitionRequest的部分字段,与已有定义做浅合并({ ...existing, ...body, name: jobName },见 server.ts)。目标定义不存在时返回404 { error: 'Job "xxx" not found' }

6.5DELETE /api/job/:jobName— 删除任务定义

curl -X DELETE \ -H "X-API-Key: secret-key" \ http://localhost:4040/api/job/send-report

删除定义的同时会取消所有同名任务实例:内部调用await agenda.cancel({ name: jobName })(server.ts),因此该操作是"定义 + 实例"双重清理。定义不存在时返回404

6.6POST /api/job/now— 立即执行

curl -X POST http://localhost:4040/api/job/now \ -H "Content-Type: application/json" \ -H "X-API-Key: secret-key" \ -d '{ "name": "send-report", "data": { "report": "daily" } }'

内部调用agenda.now(name, data),成功后返回{ success: true, jobId }。若任务名尚未定义,会先通过ensureJobDefined动态补一个定义再调度。缺少name返回400;执行异常返回500并携带错误信息。

6.7POST /api/job/once— 定时执行一次

curl -X POST http://localhost:4040/api/job/once \ -H "Content-Type: application/json" \ -H "X-API-Key: secret-key" \ -d '{ "name": "send-report", "when": "in 1 hour", "data": { "report": "daily" } }'

when字段既支持人类可读的时间表达式(如"in 1 hour"),也支持Date对象(ScheduleJobRequest.when: string | Date)。内部调用agenda.schedule(when, name, data)缺少when时返回400(测试见 api.test.ts)。

6.8POST /api/job/every— 周期执行

curl -X POST http://localhost:4040/api/job/every \ -H "Content-Type: application/json" \ -H "X-API-Key: secret-key" \ -d '{ "name": "send-report", "interval": "5 minutes", "data": { "report": "daily" } }'

interval支持类似"5 minutes"的人类可读间隔,由 Agenda 内部的human-interval库解析为毫秒数(参见 utils/processEvery.ts)。内部调用agenda.every(interval, name, data)every的完整签名(含timezoneskipImmediateskipDays等可选参数)定义在 agenda/src/index.ts 中。缺少interval时返回400

6.9POST /api/job/cancel— 取消任务

curl -X POST http://localhost:4040/api/job/cancel \ -H "Content-Type: application/json" \ -H "X-API-Key: secret-key" \ -d '{ "name": "send-report" }'

按任务名或数据条件过滤取消,请求体为{ name?, data? }

  • 两个条件都为空:返回400 { error: 'name or data is required to cancel jobs' }
  • 内部调用agenda.cancel({ name, data })(server.ts),返回{ success: true, message: 'Cancelled N job(s)', cancelledCount: N }

测试中连续调度 2 个同名任务后取消,断言cancelledCount === 2(见 api.test.ts)。

七、Webhook 执行机制深入

这是 agenda-rest 最核心的运行时行为:ensureJobDefined(server.ts)会在任务第一次被调度时,向 Agenda 注册一个动态处理器:

  1. agenda.definitions[name]已存在则跳过,保证幂等;
  2. 任务执行时,从内存定义中取出urlmethod(默认POST)、headersbody
  3. 用 Node.js 内置fetchurl发起请求,请求体取job.attrs.data ?? def.body的 JSON 序列化结果,并自动附带Content-Type: application/json
  4. 若配置了callback.url,则在主请求完成后回调该地址,上报{ job, status: 'success' | 'failed', statusCode }
  5. 请求抛出异常时记录Job xxx failed日志并向上抛错,使该任务实例进入失败状态(可由 Agenda 的重试/退避机制接管)。

这意味着:纯数据型任务(未配置url的定义)执行时只做存储/触发,不发起任何外部请求,适合作为定时数据管道的中转节点。

八、开发与测试

# 运行包级测试套件 pnpm --filter agenda-rest test # 构建包 pnpm --filter agenda-rest build

测试基于vitest+supertest,通过mongodb-memory-server起一个内存 MongoDB 完成端到端验证(见 test/api.test.ts)。测试覆盖矩阵包括:健康检查、任务定义的创建/列出/更新/删除(含 400/404/409 错误路径)、四种调度方式(now/once/every/cancel)的成功与参数缺失场景、以及 API Key 认证的三种情形。启动测试所需的全局初始化逻辑在 test/helpers/global-setup.ts,Mongo 模拟环境在 test/helpers/mock-mongodb.ts。

九、在 Agenda 生态中的定位

agenda-rest 是 Agenda 6.x 生态的组成部分,与核心包agenda(任务调度引擎)、@agendajs/mongo-backend(MongoDB 持久化后端)协同工作。其价值在于:将 Agenda 的编程式 API(define/schedule/every/cancel)封装为 HTTP 接口,让非 Node.js 技术栈或解耦的微服务也能通过 REST 方式管理任务。需要理解底层任务调度语义时,可进一步阅读 agenda 核心源码 中的everyschedulecancel实现,以及 mongo-backend 的仓库层。

十、快速参考:端点一览

方法路径功能关键入参主要错误码
GET/api/health健康检查
GET/api/job列出任务定义
POST/api/job创建任务定义name必填,url/method/headers/body/callback400、409
PUT/api/job/:jobName更新任务定义部分字段404
DELETE/api/job/:jobName删除定义并取消同名任务404
POST/api/job/now立即执行name必填,data可选400、500
POST/api/job/once定时执行一次namewhen必填400、500
POST/api/job/every周期执行nameinterval必填400、500
POST/api/job/cancel取消任务namedata至少其一400、500

配置了apiKey时,除/api/health外所有端点均需携带X-API-Key请求头,否则返回403。整个服务可通过 packages/agenda-rest/README.md 与上述源码路径进一步探索。

【免费下载链接】agenda

Lightweight job scheduling for Node.js

项目地址:https://gitcode.com/gh_mirrors/ag/agenda
点击查看免费下载
上一篇:miniblink49 中 Skia 的集成构建教程:gclient + DEPS + GYP + ninja 从零搭建
下一篇:思源宋体CN完整使用指南:7种字重免费商用,中文设计一步到位

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 16:57:10

yaml-cpp 安装指南:5 步从源码到跑通第一个 YAML 解析

yaml-cpp 安装指南&#xff1a;5 步从源码到跑通第一个 YAML 解析 【免费下载链接】yaml-cpp A YAML parser and emitter in C 项目地址: https://gitcode.com/GitHub_Trending/ya/yaml-cpp yaml-cpp 是一个符合 YAML 1.2 规范的 C 库&#xff0c;负责在 C 程序里解析和…

作者头像 李华
网站建设 2026/9/24 16:56:36

零售数据分析:如何用用户行为数据把“转化率“从3%提到8%?

做电商和零售的朋友&#xff0c;应该都对转化率这个词特别敏感。同样的流量&#xff0c;转化率3%和8%&#xff0c;业绩差的可不是一点半点。很多人转化率上不去&#xff0c;就知道瞎优化主图、改价格&#xff0c;折腾来折腾去&#xff0c;效果微乎其微。其实转化率不是靠感觉调…

作者头像 李华
网站建设 2026/9/24 16:54:56

Quick 入门实战:在 Xcode 项目中配置 Swift / Objective-C 单元测试

测试开发工具 【免费下载链接】Quick The Swift (and Objective-C) testing framework. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/qu/Quick 点击查看 免费下载 本篇指南围绕 Quick 测试框架的使用前置环节——在 Xcode 工程中正确搭建测试 Target 与跨语言测试桥…

作者头像 李华
网站建设 2026/9/24 16:51:34

dateparse4cj快速上手教程:5分钟完成安装并解析你的第一个日期字符串

dateparse4cj快速上手教程&#xff1a;5分钟完成安装并解析你的第一个日期字符串 【免费下载链接】dateparse4cj dateparse4cj 是一个基于 cangjie 标准库实现的高性能、功能丰富的日期时间解析库。它能够自动识别并解析多种格式的日期字符串&#xff0c;支持全球各种常见日期格…

作者头像 李华