오늘은 API서버에서 배치 작업을 만들어야 할 일이 생겼다. 개발력이 얼마 안되어서 배치작업을 추가해본 적이 처음이라 기록해보려고 한다.
어떤 방식이 잘 설계된 방법인지 아직 잘 가늠이 안가지만,,
서비스중인 홈페이지에서 주문이 들어오면 MongoDB에 주문 데이터가 생성된다. 다만 일반적인 쇼핑몰 홈페이지와는 달리 아직 홈페이지 내 결제기능이 없어서 해당 주문건에 대한 진행정도를 바로 처리할 수 없는 상황이다. 또, 관리자가 재고가 있는지 확인해야하고 계약을 해야하고 등등..의 과정에서 중간에 이탈도 많이 생기고 계약을 취소하는 경우도 많다.
그래서 처음 주문을 신청한지 며칠이 지나면, 해당 주문 데이터가 closed: true
상태로 변경되도록 해야한다.
nodejs에서 배치 또는 크론잡을 지원하는 모듈인 node-schedule
과 node-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
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 서버를 구현하면서 배치작업을 어떻게 돌리고 있는지 무척 궁금해졌다.