管理员定时任务 API
管理员定时任务管理路由,直接操作 pg_cron 的 cron.job 表。提供定时任务的 CRUD 操作、手动执行、日志查询和失败重置功能。
基础路径
/admin/cron-jobs认证方式
使用 combinedAuth + adminAudit 中间件。仅支持 JWT Bearer Token 认证,且需要 site:admin 权限。
Authorization: Bearer <jwt_token>允许的 Cron 端点白名单
创建和更新任务时,api_endpoint 必须在以下白名单中:
| 路径 | 说明 |
|---|---|
/cron/hello | 测试端点 - Hello World |
/cron/process-scheduled-subscriptions | 处理预约变更(每小时) |
/cron/grant-monthly-credits | 发放月度积分(每月 1 日) |
/cron/cleanup-stale-runs | 清理过期 running 记录(每分钟) |
/cron/collect-romp-stats | 采集 ROMP 统计数据(每日) |
端点列表
GET /admin/cron-jobs/endpoints
获取可用的 Cron API 端点列表(白名单)。
请求参数
无。
响应格式
json
{
"endpoints": [
{ "path": "/cron/hello", "description": "测试端点 - Hello World" },
{ "path": "/cron/process-scheduled-subscriptions", "description": "处理预约变更(每小时)" },
{ "path": "/cron/grant-monthly-credits", "description": "发放月度积分(每月1日)" }
]
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
GET /admin/cron-jobs
获取所有定时任务列表。
请求参数
无。
响应格式
json
{
"jobs": [
{
"jobid": 1,
"jobname": "hello-test",
"schedule": "*/5 * * * *",
"command": "SELECT public.trigger_cron_endpoint('/cron/hello')",
"active": true,
"last_run_time": "2026-03-07T09:55:00Z",
"last_run_status": "succeeded",
"api_endpoint": "/cron/hello"
}
]
}响应字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
jobs[].jobid | number | 任务 ID |
jobs[].jobname | string | 任务名称 |
jobs[].schedule | string | Cron 表达式 |
jobs[].command | string | 执行的 SQL 命令 |
jobs[].active | boolean | 是否启用 |
jobs[].last_run_time | string | null | 最后执行时间 |
jobs[].last_run_status | string | null | 最后执行状态 |
jobs[].api_endpoint | string | null | 解析出的 API 端点路径 |
错误码
| HTTP 状态码 | 说明 |
|---|---|
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 500 | 查询失败 |
GET /admin/cron-jobs/:jobid
获取单个任务详情。
请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
jobid | Path | number | 是 | 任务 ID |
响应格式
json
{
"job": {
"jobid": 1,
"jobname": "hello-test",
"schedule": "*/5 * * * *",
"command": "SELECT public.trigger_cron_endpoint('/cron/hello')",
"active": true,
"api_endpoint": "/cron/hello",
"..."
}
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | jobid 无效 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 404 | 任务不存在 |
| 500 | 查询失败 |
POST /admin/cron-jobs
创建定时任务。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
jobname | string | 是 | 任务名称(唯一) |
schedule | string | 是 | Cron 表达式,仅支持 5 字段(分 时 日 月 周),不支持秒级 |
api_endpoint | string | 是 | API 端点路径(必须在白名单内) |
响应格式
HTTP 201:
json
{
"job": {
"jobid": 2,
"jobname": "my-task",
"schedule": "0 * * * *",
"command": "SELECT public.trigger_cron_endpoint('/cron/hello')",
"api_endpoint": "/cron/hello",
"active": true
}
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | 缺少必填字段 / schedule 必须为 5 字段格式 / api_endpoint 格式不合法或不在白名单内 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 409 | 任务名称已存在 |
| 500 | 创建失败 |
PUT /admin/cron-jobs/:jobid
更新定时任务。
请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
jobid | Path | number | 是 | 任务 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
schedule | string | 否 | Cron 表达式,仅支持 5 字段(分 时 日 月 周),不支持秒级 |
api_endpoint | string | 否 | API 端点路径(必须在白名单内) |
active | boolean | 否 | 是否启用 |
响应格式
json
{
"job": {
"jobid": 2,
"jobname": "my-task",
"schedule": "0 */2 * * *",
"api_endpoint": "/cron/hello",
"active": true,
"..."
}
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | jobid 无效 / schedule 必须为 5 字段格式 / api_endpoint 格式不合法或不在白名单内 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 500 | 更新失败 |
DELETE /admin/cron-jobs/:jobid
删除定时任务。
请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
jobid | Path | number | 是 | 任务 ID |
响应格式
json
{
"success": true
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | jobid 无效 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 500 | 删除失败 |
POST /admin/cron-jobs/:jobid/run
手动执行定时任务。签发短期 Cron Token(60 秒有效期),通过 HTTP 调用对应的 Cron API 端点。
请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
jobid | Path | number | 是 | 任务 ID |
响应格式
成功:
json
{
"success": true,
"result": {
"success": true,
"message": "Hello 2026-03-07T10:00:00.000Z",
"executedAt": "2026-03-07T10:00:00.000Z"
},
"duration_ms": 150
}失败:
json
{
"success": false,
"error": "任务执行失败,请稍后重试",
"duration_ms": 5000
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | jobid 无效 / 无法解析 API 端点 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 404 | 任务不存在 |
| 500 | 任务执行失败 / backend_api_url 未配置 |
GET /admin/cron-jobs/:jobid/logs
获取任务执行日志。
请求参数
| 参数 | 位置 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
jobid | Path | number | 是 | - | 任务 ID |
limit | Query | number | 否 | 50 | 返回日志条数 |
响应格式
json
{
"logs": [
{
"runid": 1,
"job_pid": 12345,
"database": "postgres",
"username": "postgres",
"command": "SELECT ...",
"status": "succeeded",
"return_message": "1 row",
"start_time": "2026-03-07T09:55:00Z",
"end_time": "2026-03-07T09:55:01Z"
}
],
"total": 1
}错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | jobid 无效 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 500 | 查询失败 |
POST /admin/cron-jobs/:jobid/reset
重置任务失败计数并重新启用任务。用于手动恢复因连续失败而被自动禁用的任务。
请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
jobid | Path | number | 是 | 任务 ID |
响应格式
json
{
"success": true,
"jobname": "my-task",
"was_disabled": true,
"consecutive_failures": 0
}响应字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
jobname | string | 任务名称 |
was_disabled | boolean | 重置前是否处于禁用状态 |
consecutive_failures | number | 重置后的失败计数(总是 0) |
错误码
| HTTP 状态码 | 说明 |
|---|---|
| 400 | jobid 无效 |
| 403 | 仅支持 JWT 认证 / 缺少 site:admin 权限 |
| 404 | 任务不存在 |
| 500 | 重置失败 |
源码
- 路由文件:
apps/backend/src/routes/admin/cron.ts - Cron Token 工具:
apps/backend/src/utils/cron-token.ts