nestJS scheduling

0

오늘도 레벨업

목록 보기
2/4

nestJS- 스케쥴링

스케쥴링도 대부분의 nestjs 기능처럼 decorator로 쉽게 설정이 가능하다.

자세한 설정 방식은 공식문서에 잘 설명이 되어있다.

방법1 - 직접 cron 입력


import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';

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

  @Cron('45 * * * * *')
  handleCron() {
    this.logger.debug('Called when the current second is 45');
  }
}

방법2 - 미리 만들어진 함수 이용


import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';

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

  @Cron(CronExpression.EVERY_30_SECONDS)
  handleCron() {
    this.logger.debug('Called every 30 seconds');
  }
}

다양한 옵션은 깃헙에서 확인이 가능하다.

타임존 같은 경우 특별히 지정을 해주어야지 지정한 시간대에 맞춰서 작동한다. 그렇지 않으면 UTC기준으로 작동

참고 : nestJS-scheduling timezone

스케쥴 내용

스케쥴이 필요한 이유는 매 자정에 제출하지 않은 goal들의 score를 자동으로 만들어주기 위해서였다. 만일 score가 존재하지 않으면 chart를 그릴 때 자료가 없어서 에러가 나오기 때문에 score가 0인 자료매일 자정 전날에 대해서 추가해주는 방식으로 스케쥴을 설정했다.

이슈

access token 접근 불가 - 싱글톤

스케쥴을 돌렸는데 위와 같이 에러가 나왔다. 검색을 하다보니 이 문제는 해당 schedule이 다른 기능에 의존적이기 때문에 발생했다. 처음 api를 만들때는 각 유저에 대해서 usergoal을 찾고 그에 해당하는 score를 추가하는 방식으로 진행했다. 이 방식으로 진행을 하게 되면 문제가 발생하는데 유저의 id를 가져오는 기능(useGuard)에 의존적이기 때문에 위와 같이 id를 찾지 못한다는 에러가 나오게 되었다.

이것이 nestjs(대부분의 oop 프로그램)의 scope 개념에 기반한 것임을 알게 되었다.
useGuard를 통해서 생성되는 것은 매 요청마다 새로이 생성되는 request scope를 지니는 것이었고 이는 singletone으로 처리해야 하는 cronjob과는 맞지 않았다.
https://stackoverflow.com/a/61015839

접근

그러면 싱글톤 방식을 유지하면서 schedule을 실행할 수 있는 방법은 무엇이 있었을까? 문제에 대해서 고민을 해본 결과 아무래도 schedule을 돌려서 제출되지 않은 골들에 대해 점수를 만들어내는 작업은 한 개인identification이후 일어나는 작업이 아니라 서버 관리자 차원에서 이루어지는 작업인 것이 맞다고 생각을 했다.( 대부분의 서비스가 그렇게 작동을 하고 있다고 생각하는데... 게임 주간 보스 초기화하듯이)

해결

별도의 api인 createScoreScheduled을 만들었다. 이 api는 매 자정에 발동하고 user 전체의 goal과 score 상황을 보고 제출되지 않은 goal에 대해서 점수 0인 score를 생성한다.

  @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT, { timeZone: 'Asia/Seoul' })
  @ApiOperation({ summary: 'score 추가- 스케쥴' })
  @Post('schedule')
  createScoreScheduled() {
    return this.scoreService.createScoreScheduled();
  }

mongoAtlas - whitelist

중간에 mongoDB 정책이 바꿔었는지는 모르겠는데 위와 같은 에러가 나왔다. (정확히는 cron의 문제는 아닌 것으로 확인)

그래서 에러에서 알려주는대로 현재 ipwhitelist에 추가를 해주니 mongoDB에 데이터가 적절히 삽입이 될 수 있었다. (15:00로 나오는 이유는 몽고dbutc 기준으로 찍히기 때문에 24- 9 = 15)

이후에 실제 배포한 ip도 등록을 해주어 해당 ip에서도 cron이 잘 작동하도록 설정해주었다. (mongo-atlas - network- access에서 확인 가능)

profile
기록을 통해 한 걸음씩 성장ing!

0개의 댓글