5 · Cron jobs / background work
บทนี้ยืนยันสถานะ scheduler ของ ai-recruitment-api (branch: prod) และแยกให้อ่านชัดระหว่าง "ไม่มี cron" กับงานหนักที่ยังเป็น request-scoped
ดู pipeline on-demand: 02 Core pipeline
สรุปสั้น
ไม่พบ cron job, schedule module, หรือ long-running worker ใน repo นี้
ทุกงาน AI / DB / Puppeteer ทำงานภายในวงชีวิตของ HTTP request แล้วจบ — ไม่มีคิวพื้นหลังแยก process
หลักฐานว่าไม่มี scheduler
1) package.json dependencies
รายการ dependencies ที่ประกาศ (package.json:10-24):
axios, canvas, cors, dotenv, express, form-data, jsonwebtoken, mssql, multer, openai, qs, sharp, puppeteer
ไม่มี แพ็กเกจกลุ่มนี้:
| แพ็กเกจที่มักใช้ทำ cron | พบใน repo? |
|---|---|
node-cron | ไม่ |
node-schedule | ไม่ |
@nestjs/schedule | ไม่ (และไม่ใช่ NestJS) |
bull / bullmq / agenda | ไม่ |
bee-queue | ไม่ |
Scripts มีแค่ start / dev (package.json:6-8) — ไม่มี worker, cron, schedule
2) ค้น pattern ในซอร์ส
ค้นทั้งไฟล์ .js ของ repo ไม่พบ:
setInterval(สำหรับ business jobsetTimeout(ที่ใช้เป็น periodic scheduler ระดับแอป@Cron/CronExpression(Nest)cron.schedulenode-cron
(มีเพียง timeout ของ HTTP client เช่น remove.bg timeout: 30000 ซึ่งเป็น per-request ไม่ใช่ cron)
3) ไม่มีโฟลเดอร์ tasks / jobs
โครงสร้างมี controllers/, services/, middleware/, config/ — ไม่มี tasks/, jobs/, cron/, workers/
Service เดียวคือ removeBgService.js ซึ่งถูกเรียกจาก controller แบบ sync ใน request (module2_2_controller.js:194)
สิ่งที่ "ดูเหมือน background" แต่ไม่ใช่ cron
| พฤติกรรม | ทำไมไม่ใช่ cron | แหล่ง |
|---|---|---|
| Puppeteer launch ต่อ combine request | อยู่ใน combineJobPosting แล้ว browser.close() ใน finally | combineJobPostingController.js:377-446 |
Promise.all สร้างภาพ 3 ใบ | concurrency ภายใน request เดียว | module2_2_controller.js:174-184 |
Logger เขียนไฟล์ async ด้วย fs.appendFile callback | I/O ของ log ไม่ใช่ business schedule | logger.js:34-38 |
| OpenAI 4 ครั้งต่อ job description | sequential awaits ใน request | generateJobDescriptionController.js:230-334 |
ถ้า request ถูกยกเลิกกลางทาง โดยทั่วไปงานย่อยที่ยังไม่ await อาจยังรันจนจบใน process (พฤติกรรม Node ทั่วไป) — แต่ไม่มี mechanism ที่จะ "กลับมารันใหม่ตามเวลา" เมื่อไม่มี request
ผลต่อ operations
| หัวข้อ | ผล |
|---|---|
ไม่มี midnight sync ของ jobReqPosition | ตรงกับข้อ UNVERIFIED ใน 03 — sync ถ้ามี ต้องอยู่นอก repo |
| Horizontal scale | แต่ละ replica รับ HTTP อิสระ; ไม่มี leader election สำหรับ job |
| Cost control | ไม่มี batch off-peak — ทุก generate เกิดตอนผู้ใช้กด |
| Failure recovery | ไม่มี retry queue; client ต้องเรียก endpoint ซ้ำเอง |
| Health | ไม่มี liveness ที่เช็ค cron lag เพราะไม่มี cron |
เปรียบเทียบกับ sibling services ใน Volume 6
| Service | Scheduler |
|---|---|
benefit-api | มี @nestjs/schedule + cron modules (ดู benefit-api บท 05) |
recruitment-api | มีบาง jobs (ดู recruitment-api บท 05) |
job-scheduler-api | เป็นตัวรวม schedule โดยหน้าที่ |
ai-recruitment-api | ไม่มี |
การออกแบบนี้สอดคล้องกับบทบาท "AI helper ถูกเรียกจาก back-office" ไม่ใช่ระบบที่ต้อง sync ข้อมูลเป็นรอบ
ถ้าอนาคตต้องเพิ่มงานตามเวลา
แนวทางที่เข้ากับ stack ปัจจุบันโดยไม่เปลี่ยน framework:
- เพิ่ม
node-cronใน process เดียวกับ Express — ง่าย แต่ผูกกับ web replica - แยก worker process + คิว — เหมาะถ้าต้อง generate จำนวนมาก / จำกัด concurrency ของ Puppeteer
- ใช้
job-scheduler-apiของแพลตฟอร์มเรียก HTTP เข้า endpoint ที่มีอยู่ (ยังต้องมี auth JWT)
ข้อใดข้อหนึ่งต้องออกแบบ auth สำหรับ service-to-service ให้ชัด เพราะตอนนี้มีแค่ shared JWT secret โดยไม่มี role (ดู 04)
สรุปหลักฐานหนึ่งบรรทัด
ai-recruitment-api/package.json (branch: prod) + tree ของ controllers//services/ ยืนยันว่า service นี้เป็น pure request/response AI helper โดยไม่มี scheduled background jobs
ไป บท 6 Scorecard →