src/server/jobs/queue.ts
此代码来自构建时的仓库快照。修改源码后重新构建即可更新。
import { Queue } from 'bullmq';
import IORedis from 'ioredis';
import { MAX_TASK_ATTEMPTS } from '@/shared/tasks';
export type TaskJob = { taskId: string; run: number };
export const queueName = 'background-tasks';
export const queuePrefix = () => process.env.QUEUE_PREFIX ?? 'teamdesk';
export const heartbeatKey = (prefix = queuePrefix()) =>
`${prefix}:worker-heartbeat`;
export function createRedis(worker = false) {
if (!process.env.REDIS_URL) throw new Error('请配置 REDIS_URL');
// Worker 允许持续重连;Web 端快速返回失败,不能让一次 HTTP 请求无限等待 Redis。
const client = new IORedis(process.env.REDIS_URL, {
maxRetriesPerRequest: worker ? null : 1,
enableOfflineQueue: worker,
connectTimeout: 3000,
retryStrategy: (times) => Math.min(times * 500, 5000),
});
client.on('error', () => {
/* 连接故障由健康检查和 Worker 日志统一报告,不打印连接串。 */
});
return client;
}
export function createTaskQueue(connection: IORedis) {
return new Queue<TaskJob>(queueName, {
connection,
prefix: queuePrefix(),
defaultJobOptions: {
attempts: MAX_TASK_ATTEMPTS,
backoff: { type: 'exponential', delay: 2000 },
removeOnComplete: { age: 86400, count: 1000 },
removeOnFail: { age: 604800, count: 1000 },
},
});
}
export function taskJobId(id: string, run: number) {
return `${id}-${run}`;
}