nodejs, express API 서버에서 배치 작업하기

fana·2020년 4월 7일
1
post-thumbnail

오늘은 API서버에서 배치 작업을 만들어야 할 일이 생겼다. 개발력이 얼마 안되어서 배치작업을 추가해본 적이 처음이라 기록해보려고 한다.
어떤 방식이 잘 설계된 방법인지 아직 잘 가늠이 안가지만,,

TODO

서비스중인 홈페이지에서 주문이 들어오면 MongoDB에 주문 데이터가 생성된다. 다만 일반적인 쇼핑몰 홈페이지와는 달리 아직 홈페이지 내 결제기능이 없어서 해당 주문건에 대한 진행정도를 바로 처리할 수 없는 상황이다. 또, 관리자가 재고가 있는지 확인해야하고 계약을 해야하고 등등..의 과정에서 중간에 이탈도 많이 생기고 계약을 취소하는 경우도 많다.

그래서 처음 주문을 신청한지 며칠이 지나면, 해당 주문 데이터가 closed: true 상태로 변경되도록 해야한다.

구현

nodejs에서 배치 또는 크론잡을 지원하는 모듈인 node-schedulenode-cron을 모두 살펴봤다. 내가 구현하려는 기능에서는 어떤 것을 사용해도 무관해보였기 때문에 node-cron을 사용하기로 했다. npm에 올라가있는 도큐먼트를 일단 찬찬히 훑어보고, 이제 막 시작하려는 찰나에 문제가 생겼다.

현재 서비스는 AWS EC2에 올라가 있고, PM2를 사용하여 관리를 하고있다. 보통

> pm2 start app.js --name api-server

라는 명령어로 인스턴스를 구동시키게 되는데, 해당 배치잡은 root/batch/something/SomeBatchJob.js에 있기 때문에 이 스크립트를 어떻게 시작해야 하는 고민이 생겼기 때문에...

몇 가지 방법을 찾아보고 시도해보긴 했는데..

  • 첫번째 방법: 라우터에 node-cron을 달기
exports.subscribe = async (req, res) => {
  try {
    cron.schedule(..., () => {
      // do something
    }).start();
    
  } catch (err) {
   res.status(400)
   res.json({ success: false, message: err.message })
}
  
 exports.unsubscribe = async (req, res) => {
   try {
     cron.schedule(..., () => {
       // do something
     }).destroy();
   } catch (err) {
    // handling errors 
   }
 }

위와 같은 방법으로 라우터에 배치잡을 붙인다. 위 방법으로는 인스턴스를 재시작하거나, 빌드를 다시하면 해당 라우터를 한번은 꼭 불러줘야 해당 배치잡이 시작된다. 애초에 위 소스코드의 설명도 어떤 사용자가 "구독"했을 때 뉴스레터를 발송하는 등...과 관련된 것이어서 내가 구현하려는 기능과는 다른 것 같았다.

  • 두번째 방법: app.js에 냅다 불러와서 실행시키기
// app.js
const express = require("express");
const mongoose = require("mongoose");
const someBatchJob = require("someBatchJob");
const anotherBatchJob = require("anotherBatchJob");

[...]
 
app.use("/api", require("./routes/api"));

[...]
 
/* BATCH TASKS */
someBatchJob();
anotherBatchJob();
// anotherBatchJob.js
const cron = require("node-cron");
const Model = require("../../models/model");

const anotherBatchJob = () => {
  cron.schedule("0 5 0 * * *", async() => {
    	try {
    	checkIfOrdersDeprecated();
    	deprecatedOrderToClosedStatus();
    	doOtherThings();
        } catch (err) {
         // handling errors
        }
  }).start();
}

module.exports = anotherBatchJob;

위와 같은 방법으로 app.js에 바로 불러들여서 해당 스크립트를 실행시키도록 했다. 추후에 배치 돌릴 일이 많아지면 index.js를 만들지 뭐 라는 단순한 생각으로...
맞게 구현한건지 모르겠고 다른 개발자사마들은 API 서버를 구현하면서 배치작업을 어떻게 돌리고 있는지 무척 궁금해졌다.

마침

  • 회사에서도 VELOG를 거의 매일 들어와서 보는데... 여러 개발자분들이 공부하는거나 정리를 해두시는것 읽으면서 나도 언젠가 시작해야지 시작해야지 하다가 이제서야 시작한다.
  • 생각보다 정리를 하는것도, 글을 쓰는것도 너무너무 어렵다.
  • 꾸준히 쓰자는 마음을 먹으면서 마침~!

0개의 댓글