Nestjs框架: nestjs-schedule模块中的三类定时任务
三类定时任务
- task schedule 要做的三件事情
- 添加定时任务
- 删除定时任务
- 获取所有定时任务的状态
- 什么类型的任务适合使用 task.schedule 模块
- 周期性任务:如每天、每小时、每周执行的任务,适合使用 taskschedule 模块
- 每天看签到任务是否完成, 未完成则给用户添加 task queue 的消息
- 这是周期性任务 和 task queue 配合的示例
- 简单任务:像系统状态或接口状态的检查,可通过发起请求判断,将响应数据存储到数据库方便后续读取
- 轻量级任务:任务不常执行且任务量不大的情况,适合使用 task schedule (非高并发任务)
- 周期性任务:如每天、每小时、每周执行的任务,适合使用 taskschedule 模块
- task schedule 不适合做什么
- 给用户发送指定日期某一分,某一秒的消息
- 如果是大量高并发的任务,使用 task queue
- task queue 可以实现给用户发送指定日期某一分,某一秒的消息
- task queue 在 nestjs 中有一个 nestjs bull + redis 的方案
- task queue 其他方案: RabbitMQ,MessageMQ, Kafka 方案
合理规划 tasks 定时任务
- common
- cron
- tasks
- log-db-cron.service.ts
- index.ts
- tasks.module.ts
- tasks.service.ts
- tasks
- cron
1 ) cron/tasks/log-db-cron.service.ts
import { Injectable } from '@nestis/common';
import { Cron } from '@nestjs/schedule';
import { SshService } from '@/utils/ssh/ssh.service';@Injectable();
export class LogDbCronService {constructor(private sshService: sshService) {}@Cron('0 * 0 * *', {name: 'logdb-cron'})handleCron(){//备份:连接到MongoDB并导出对应的db中的collections的数据//滚动记录:删除已有的collections的数据//1.删除当前collections中的已备份数据//2.之前备份的collections->对比collection备份的时间,如果超过t天/hours的规则,则删除const containerName = 'mongo-mongo-1';const uri='mongodb: //root: example@localhost: 27017/nest-logs';const now = new Date();const collectionName = 'log';const outputPath =`/tmp/logs-${now.getTime()}`;const hostBackupPath = '/srv/logs';const cmd =`docker exec -i ${containerName} mongodump --uri=${uri} --collection=${collectionName} --out=${outputPath}`;const cpCmd =`docker cp ${containerName}:${outputPath} ${hostBackupPath}`;await this.sshService.exec(`${cmd} && ${cpCmd}`)await this.sshService.exec(`ls-la ${hostBackupPath}`);const delCmd = `find ${hostBackupPath} -type d -mtime +30 -exec rm-rf {}\\;`;await this.sshService.exec(delCmd)const res = await this.sshService.exec(`ls-la ${hostBackupPath}`);console.log('~ TasksService ~ handleCron ~ res:', res);}
}
2 ) cron/tasks/index.ts
import { Provider } from '@nestjs/common';
import { LogDbCronService } from './tasks/log-db-cron.service';export const CronProviders: Provider[] = [LogDbCronService];
3 ) tasks.module.ts
$ nest g mo common/cron/tasks --no-spec --flat -d
生成 nest g mo common/cron/tasks.module.ts
import { Module } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { ScheduleModule } from '@nestjs/schedule';
import { CronProviders } from './tasks/index';@Module({imports: [ScheduleModule.forRoot()],providers: [TasksService, ...CronProviders],exports: [TasksService],
})export class TasksModule {}
4 ) task.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { SchedulerRegistry } from '@nestjs/schedule';
import { CronJob } from 'cron';@Injectable()
export class TasksService {logger = new Logger('TasksService');constructor(private schedulerRegistry: SchedulerRegistry){}//添加定时任务addCronJob(name: string, cronTime: string, cb:()=> void): void {const job = new CronJob(cronTime, cb);this.schedulerRegistry.addCronJob(name, job);job.start();this.logger.log(`Job ${name} added and started`);}// 删除定时任务deleteCronJob(name: string): void {this.schedulerRegistry.deleteCronJob(name);this.logger.warn(`Job ${name} deleted`);}// 获取所有的定时任务的状态getCrons() {const jobs = this.schedulerRegistry.getCronJobs();jobs.forEach((value, key) => {let next;try {next = value.nextDate().toJSDate();} catch(e) {next = 'error: next fire date is in the past!';}this.logger.log(`job: ${key} -> next: ${next}`); // key 是 id, next 下一次执行任务的时间});}
}
这是控制定时任务的 添加,删除,获取所有的定时任务
- 更多参考官网
- task-scheduling
5 ) 使用
-
在某个模块,比如 auth.mdoule.ts 导入 TasksModule
import { Module } from '@nestjs/common'; import { TasksModule } from '@/common/cron/tasks.module';@Module({imports: [TasksModule,] })export class AuthModule {}
-
之后再 auth.controller.ts 导入
import { Module, Get } from '@nestjs/common'; import { TasksService } from '../../common/cron/tasks.service';@Controller('auth'); export class AuthController {constructor(private tasksService: TasksService) {}@Get('add-job')getAddJob() {// 每分钟执行一次 写死的任务名称this.tasksService.addCronJob('test', '*****', () => {console.log('hello schedule job');});return 'created';}@Get('delete-job')deleteJob() {this.tasksService.deleteCronJob('test'); // 写死的任务名称return 'deleted';}@Get('get-jobs')getJobs() {this.tasksService.getCrons();return 'get jobs';} }
-
以上都是简单的测试,调用对应的 api 即可测试