三类定时任务
- 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 下一次执行任务的时间
});
}
}
这是控制定时任务的 添加,删除,获取所有的定时任务
- 更多参考官网
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 即可测试