Skip to content

任务队列系统

EcoCtrl 使用 pg-boss 实现可靠的后台任务处理。所有任务存储在 PostgreSQL 中,由运行在 API 服务同一进程中的 Worker 消费。

架构

API 请求或定时触发器


  boss.send('queue-name', payload)


  pg-boss (PostgreSQL 表)
   ─ pg boss.job (待处理任务)
   ─ pg boss.archive (已完成任务归档)


  Worker 轮询 → 执行 handler → 更新状态


  完成 / 失败(重试或死信)

pg-boss 直接使用 Fastify 所在的 PostgreSQL 数据库连接,不需要独立的队列基础设施。任务元数据和状态都存储在数据库的 pgboss schema 下,简化了运维复杂度。

初始化

队列系统通过 queue/pgboss.ts 初始化:

typescript
import PgBoss from "pg-boss";

const boss = new PgBoss({
  schema: "pgboss", // 独立 schema 避免表名冲突
  connectionString: DATABASE_URL,
});

await boss.start();

关键初始化参数:

参数说明
schema独立 schema 名称,默认 pgboss
connectionStringPostgreSQL 连接字符串
pollIntervalSeconds轮询新任务间隔(默认 2 秒)
retentionDays完成任务保留天数(默认 30 天)

任务类型

任务队列名说明
报表生成report-generation异步生成 PDF/CSV 能耗报表
数据库备份backup定时备份数据库到存储
工作流执行workflow-execution执行工作流 DSL 定义的任务

发送任务

typescript
await boss.send(
  "report-generation",
  {
    reportId: "rpt_123",
    format: "pdf",
    userId: "user_456",
  },
  {
    retryLimit: 3,
    retryDelay: 60, // 秒
  },
);

Worker

Worker 在 queue/worker.ts 中注册:

typescript
import { getWorker } from "./queue/pgboss";

const worker = await getWorker();

// 注册报表生成处理器
await worker.work("report-generation", async (job) => {
  const { reportId, format } = job.data;
  // 执行报表生成...
});

运行模式

  • 同一 Node.js 进程中运行(不独立部署)
  • 开发环境自动启动(伴随 API 服务)
  • 生产环境同进程运行
  • 支持优雅关闭(监听 SIGTERM 信号完成当前任务后退出)

重试与死信

指数退避

任务失败后按指数增长间隔重试:

  • 第 1 次重试:60 秒后
  • 第 2 次重试:120 秒后
  • 第 3 次重试:240 秒后
  • ...

退避公式:retryDelay * 2^(attempt - 1),默认初始延迟 60 秒。

死信策略

条件行为
重试次数未达上限按指数退避重新排队
达到最大重试次数任务标记为 failed 进入死信状态
死信任务保留在 pgboss.job 表中,状态为 failed,可供人工审查
手动重新排队通过 pg-boss API 或 SQL 可将死信重新加入队列

死信重入

sql
-- 查看死信任务
SELECT * FROM pgboss.job WHERE state = 'failed';

-- 手动重新排队(设置新状态为 created)
UPDATE pgboss.job SET state = 'created' WHERE id = 123;

监控

通过 pg-boss 内置表监控队列状态:

内容
pgboss.job所有任务记录(含待处理、运行中、失败)
pgboss.archive已完成任务归档
pgboss.schedule定时任务配置

常用监控查询

sql
-- 各队列待处理任务数
SELECT name, COUNT(*) FROM pgboss.job
WHERE state = 'created' GROUP BY name;

-- 最近失败的报表生成任务
SELECT * FROM pgboss.job
WHERE name = 'report-generation' AND state = 'failed'
ORDER BY created_on DESC LIMIT 10;

相关文件

  • packages/server/src/queue/pgboss.ts — pg-boss 初始化与配置
  • packages/server/src/queue/worker.ts — Worker 注册与处理器
  • packages/server/src/queue/types.ts — 任务相关类型定义

基于 MIT 协议发布