[NestJS] Task Scheduling

Hocaron·2022년 5월 21일
1

NestJS

목록 보기
11/12

라이브러리 설치

$ npm install --save @nestjs/schedule
$ npm install --save-dev @types/cron

사용해보자

  • AppModule에 import
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';

@Module({
  imports: [
    ScheduleModule.forRoot()
  ],
})
export class AppModule {}
  • service에서 선언
import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';

@Injectable()
export class TasksService {
  private readonly logger = new Logger(TasksService.name);

  @Cron('45 * * * * *') // 45초마다 실행
  handleCron() {
    this.logger.debug('Called when the current second is 45');
  }
}

@Cron 데코레이터에서 사용할 수 있는 패턴

  • Asterisk (e.g. *) : every
  • Ranges (e.g. 1-3,5)
  • Steps (e.g. */2)
* * * * * *
| | | | | |
| | | | | day of week
| | | | month
| | | day of month
| | hour
| minute
second (optional)
패턴설명
* * * * * *every second
45 * * * * *every minute, on the 45th second(매분 45초마다)
10 * * *every hour, at the start of the 10th minute(매시, 10분마다. (1시 10분, 2시 10분...))
0 /30 9-17 * *every 30 minutes between 9am and 5pm
0 30 11 * * 1-5Monday to Friday at 11:30am

@Cron() decorator 추가 옵션들

패턴설명
nameUseful to access and control a cron job after it's been declared.
timeZoneSpecify the timezone for the execution. This will modify the actual time relative to your timezone. If the timezone is invalid, an error is thrown. You can check all timezones available at Moment Timezone website.
utcOffsetThis allows you to specify the offset of your timezone rather than using the timeZone param.
  • 사용예시
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';

@Injectable()
export class NotificationService {
  @Cron('* * 0 * * *', {
    name: 'notifications',
    timeZone: 'Europe/Paris',
  })
  triggerNotifications() {}
}

Dynamic cron

기존 cron 제어하기

name 값을 준 cron을 아래와 같이 사용할 수 있다.

// 매분의 5초마다 실행 (1분 5초, 2분 5초... 따라서 간격은 1분)

@Cron('5 * * * * *', { name: 'myJob' })
async checkForPayments() {
  console.log('checking for payments');
  const cronJob = this.schedulerRegistry.getCronJob('myJob');
  cronJob.stop(); // 결과적으론 1번만 실행하고 cronJob이 멈추게 됨
}

사용할 수 메서드

stop() - stops a job that is scheduled to run.
start() - restarts a job that has been stopped.
setTime(time: CronTime) - stops a job, sets a new time for it, and then starts it
lastDate() - returns a string representation of the last date a job executed
nextDates(count: number) - returns an array (size count) of moment objects representing upcoming job execution dates.
SchedulerRegistry.addCronJob() : cron 생성
  • 기존 cron 을 제어하는 것 외에도 SchedulerRegistry.addCronJob() 메서드를 통해서 cron을 생성할 수도 있다.
addCronJob(name: string, seconds: string) {
  const job = new CronJob(`${seconds} * * * * *`, () => {
    this.logger.warn(`time (${seconds}) for job ${name} to run!`);
  });

  this.scheduler.addCronJob(name, job);
  job.start();

  this.logger.warn(
    `job ${name} added for each minute at ${seconds} seconds!`,
  );
}
  • SchedulerRegistry.deleteCronJob() : cron 삭제
deleteCron(name: string) {
  this.scheduler.deleteCronJob(name);
  this.logger.warn(`job ${name} deleted!`);
}
  • SchedulerRegistry.getCronJobs() : cron 확인하기
getCrons() {
  const jobs = this.scheduler.getCronJobs();
  jobs.forEach((value, key, map) => {
    let next;
    try {
      next = value.nextDates().toDate();
    } catch (e) {
      next = 'error: next fire date is in the past!';
    }
    this.logger.log(`job: ${key} -> next: ${next}`);
  });
}

적용해보자

  • 사용자가 설정한 시간 후에 푸시 알림을 보내는 기능이 필요하다면?
    const date = new Date(createPushNotificationDto.date); // 사용자가 설정한 시간
    const job = new CronJob(date, async () => {
      await admin
        .messaging()
        .send(message)
        .then((response) => {
          console.log('Successfully sent message:', response);
        })
        .catch((error) => {
          console.log('Error sending message:', error);
        });
    });

    this.schedulerRegistry.addCronJob(
      `${createPushNotificationDto.userId}-${date}`,
      job,
    );
    job.start();
profile
기록을 통한 성장을

0개의 댓글