2024-10-28-【研发】nestjs动态管理定时任务

背景

在实际的业务场景中,定时任务的管理往往是动态的,比如:邮件定时推送、数据统计定时刷新等,需要根据业务的变化,动态的添加、删除、修改定时任务执行时间及任务内容。为了解决通过@Cron(‘0 10 16 * * 1-5’)注解来实现定时任务固定执行时间的局限性。提高灵活性,及可扩展性。

1. 相关依赖包

安装依赖pnpm add @nestjs/schedule
对应版本"@nestjs/schedule": "^2.2.1",

2. nestjs 动态定时任务实现

2.1 创建定时任务服务

包含创建任务、删除任务、判断任务是否存在等功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { SchedulerRegistry } from "@nestjs/schedule";
import { CronJob } from "cron";

// 自定义定时任务服务
@Injectable()
export class SchedulerTaskService {
constructor(
// 定时任务注册器
private readonly schedulerRegistry: SchedulerRegistry
) {}

// 执行任务
public async executeTask(
// 任务名称
name: string,
// cron表达式
cronExpression: Date | string,
// 回调函数
callback: () => void,
// 执行完后是否需要删除
needDel?: boolean
) {
try {
// 创建定时任务
const job: CronJob = new CronJob(cronExpression, () => {
if (callback) {
callback();
}
// 删除定时任务
needDel && this.deleteCron(name);
});
// 添加定时任务
this.schedulerRegistry.addCronJob(name, job);
// 启动定时任务
job.start();
} catch (e) {
throw new HttpException(e, HttpStatus.BAD_REQUEST);
}
}
// 删除任务
public deleteCron(name: string) {
this.schedulerRegistry.deleteCronJob(name);
}

// 判断是否存在任务
public doesExist(type: "cron" | "timeout" | "interval", name: string) {
return this.schedulerRegistry.doesExist(type, name);
}
}

2.2 定时任务列表

配置定时任务列表,可以本地存储也可以远程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const schedulerTaskList = [
// 资金相关 === start
{
taskName: "schedulerTask1",
service: "mailService",
func: "pushMail",
cron: "0 10 16 * * 1-5",
},
{
taskName: "schedulerTask1",
service: "newsService",
func: "crawlNewsData",
cron: "0 41 11 * * 1-5",
},
];
export { schedulerTaskList };

2.3 初始化动态定时任务

  1. 项目启动时,执行定时任务初始化 main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppController } from './app.controller.ts';

...
async function bootstrap() {
const app: NestExpressApplication = await NestFactory.create<NestExpressApplication>(AppModule);

// 通过依赖注入获取控制器实例
const appController = app.get(AppController);
appController.initSchedulerTask();
...
}
bootstrap();
  1. app.controller.ts添加定时任务初始化方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 初始化定时任务
*/
async initSchedulerTask() {
// schedulerTaskList 定时任务列表,可以从配置文件中读取,也可以来源于数据库
schedulerTaskList.forEach(task => {
this.schedulerTaskService.executeTask(task.taskName, task.cron, async () => {
try {
await this[task.service][task.func]();
} catch (e) {
// 报错后 通知企微
this.qyWechatNotice.notice(task.service, `[${task.func}]出错了:${e}`);
}
});
});
}

2024-10-28-【研发】nestjs动态管理定时任务
https://zhangyingxuan.github.io/2024-10-28-【研发】nestjs动态管理定时任务/
作者
blowsysun
许可协议