背景
在实际的业务场景中,定时任务的管理往往是动态的,比如:邮件定时推送、数据统计定时刷新等,需要根据业务的变化,动态的添加、删除、修改定时任务执行时间及任务内容。为了解决通过@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, 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 = [ { 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 初始化动态定时任务
- 项目启动时,执行定时任务初始化
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();
|
app.controller.ts添加定时任务初始化方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
async initSchedulerTask() { 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}`); } }); }); }
|