Parcourir la source

Merge commit '36c8c7bf00ebd5edcd028c7a0231c74b15dc12e6' into staging

yazid138 il y a 5 jours
Parent
commit
942e0b4bca
4 fichiers modifiés avec 91 ajouts et 51 suppressions
  1. 2 2
      app.js
  2. 3 38
      controller/v1/auto.controller.js
  3. 54 0
      services/batchSanksi.service.js
  4. 32 11
      worker/waWorker.js

+ 2 - 2
app.js

@@ -12,8 +12,8 @@ const app = express()
 
 require('./config/db')()
 
-// Start background worker for async WA sending
-startWorker(3000)
+// Start background workers: WA every 3s, batch every 30s
+startWorker(3000, 30000)
 
 app.use(logger('dev'))
 app.use(express.json())

+ 3 - 38
controller/v1/auto.controller.js

@@ -15,6 +15,7 @@ const kontakModel = require('../../model/kontak.model')
 const pemantauanModel = require('../../model/pemantauan.model')
 const batchModel = require('../../model/batch.model')
 const pddiktiService = require('../../services/v2/pddikti.service')
+const { processBatchUpdateSanksi } = require('../../services/batchSanksi.service')
 
 exports.keberatan = handleError(async (req, res) => {
   const dataSanksi = await sanksiModel
@@ -369,45 +370,9 @@ exports.berakhirSanksi = handleError(async (req, res) => {
 })
 
 exports.batchUpdateSanksi = handleError(async (req, res) => {
-  const data = await batchModel.find({
-    type: UPDATE_SANKSI
-  })
-    .populate({
-      path: 'sanksi',
-      populate: ['laporan']
-    })
-  let error = []
-  await Promise.all(data.map(async e => {
-    const { sanksi } = e
-    if (!sanksi?.laporan) return
-    try {
-      await pddiktiService.updatePDDIKTI({
-        ptKode: sanksi.laporan.pt.kode,
-        noSanksi: sanksi.laporan.no_laporan,
-        fromDate: moment(sanksi.masa_berlaku.from_date).format('YYYY-MM-DD'),
-        levelSanksi: sanksi.levelSanksi,
-        terimaSanksi: moment(sanksi.tanggal_terima_sanksi).format('YYYY-MM-DD')
-      })
-      await logModel.create({
-        aktivitas: `Server berhasil mengirimkan data Ke API PDDIKTI untuk update Status PT ${sanksi.laporan.pt.nama}`
-      })
-      await batchModel.deleteOne(e._id)
-    } catch (e) {
-      error.push(e.message)
-      await Promise.all([
-        logModel.create({
-          aktivitas: `Server gagal mengirimkan data Ke API PDDIKTI untuk update Status PT ${sanksi.laporan.pt.nama}, dengan error ${e.message}`
-        }),
-        pemantauanModel.deleteOne({
-          laporan: sanksi.laporan._id,
-          sanksi: sanksi._id,
-          action: CREATE_SANKSI
-        })
-      ])
-    }
-  }))
+  const { processed, error } = await processBatchUpdateSanksi()
   return response.success(res, {
-    message: error.length ? 'Ada beberapa data yang tidak bisa dikirim ke PDDIKTI' : 'Berhasil mengirim data ke PDDIKTI',
+    message: error.length ? 'Ada beberapa data yang tidak bisa dikirim ke PDDIKTI' : `Berhasil mengirim data ke PDDIKTI (${processed} data)`,
     data: { error },
   })
 })

+ 54 - 0
services/batchSanksi.service.js

@@ -0,0 +1,54 @@
+const batchModel = require('../model/batch.model')
+const pemantauanModel = require('../model/pemantauan.model')
+const logModel = require('../model/log.model')
+const pddiktiService = require('./v2/pddikti.service')
+const moment = require('moment')
+const { UPDATE_SANKSI, CREATE_SANKSI } = require('../utils/constanta')
+const { logInfo, logError } = require('../utils/logger')
+
+/**
+ * Proses semua batch job UPDATE_SANKSI: kirim ke PDDIKTI, hapus batch kalau sukses,
+ * biarkan tersimpan (untuk retry) kalau gagal.
+ * Dipakai oleh endpoint manual (auto.controller.batchUpdateSanksi) dan worker background.
+ */
+exports.processBatchUpdateSanksi = async () => {
+  const data = await batchModel.find({ type: UPDATE_SANKSI })
+    .populate({ path: 'sanksi', populate: ['laporan'] })
+
+  if (!data.length) return { processed: 0, error: [] }
+
+  const error = []
+  await Promise.all(data.map(async (e) => {
+    const { sanksi } = e
+    if (!sanksi?.laporan) return
+    try {
+      await pddiktiService.updatePDDIKTI({
+        ptKode: sanksi.laporan.pt.kode,
+        noSanksi: sanksi.laporan.no_laporan,
+        fromDate: moment(sanksi.masa_berlaku.from_date).format('YYYY-MM-DD'),
+        levelSanksi: sanksi.levelSanksi,
+        terimaSanksi: moment(sanksi.tanggal_terima_sanksi).format('YYYY-MM-DD')
+      })
+      await logModel.create({
+        aktivitas: `Server berhasil mengirimkan data Ke API PDDIKTI untuk update Status PT ${sanksi.laporan.pt.nama}`
+      })
+      await batchModel.deleteOne({ _id: e._id })
+      logInfo('BATCH_SANKSI', 'Batch item processed', { batchId: e._id, pt: sanksi.laporan.pt.nama })
+    } catch (err) {
+      error.push(err.message)
+      logError('BATCH_SANKSI', 'Batch item failed', { batchId: e._id, pt: sanksi.laporan?.pt?.nama, error: err.message })
+      await Promise.all([
+        logModel.create({
+          aktivitas: `Server gagal mengirimkan data Ke API PDDIKTI untuk update Status PT ${sanksi.laporan.pt.nama}, dengan error ${err.message}`
+        }),
+        pemantauanModel.deleteOne({
+          laporan: sanksi.laporan._id,
+          sanksi: sanksi._id,
+          action: CREATE_SANKSI
+        })
+      ])
+    }
+  }))
+
+  return { processed: data.length, error }
+}

+ 32 - 11
worker/waWorker.js

@@ -1,13 +1,16 @@
 const pddiktiService = require('../services/v2/pddikti.service')
 const waJobService = require('../services/waJob.service')
+const { processBatchUpdateSanksi } = require('../services/batchSanksi.service')
 const { logInfo, logError } = require('../utils/logger')
 
-let isRunning = false
-let timer = null
+let isWaWorkerRunning = false
+let isBatchWorkerRunning = false
+let waTimer = null
+let batchTimer = null
 
-const processJobs = async () => {
-  if (isRunning) return
-  isRunning = true
+const processWaJobs = async () => {
+  if (isWaWorkerRunning) return
+  isWaWorkerRunning = true
 
   try {
     const job = await waJobService.processNextJob()
@@ -28,19 +31,37 @@ const processJobs = async () => {
   } catch (err) {
     logError('WA_WORKER', 'Error in worker tick', { error: err.message })
   } finally {
-    isRunning = false
+    isWaWorkerRunning = false
   }
 }
 
-const startWorker = (intervalMs = 3000) => {
-  logInfo('WA_WORKER', `Starting WA Background Worker (interval: ${intervalMs}ms)`)
+const processBatchJobs = async () => {
+  if (isBatchWorkerRunning) return
+  isBatchWorkerRunning = true
+
+  try {
+    const { processed, error } = await processBatchUpdateSanksi()
+    if (processed > 0) {
+      logInfo('BATCH_WORKER', `Processed ${processed} batch items`, { errors: error.length })
+    }
+  } catch (err) {
+    logError('BATCH_WORKER', 'Error in batch worker tick', { error: err.message })
+  } finally {
+    isBatchWorkerRunning = false
+  }
+}
+
+const startWorker = (waIntervalMs = 3000, batchIntervalMs = 30000) => {
+  logInfo('WORKER', `Starting Background Workers (WA: ${waIntervalMs}ms, Batch: ${batchIntervalMs}ms)`)
   waJobService.resetStuckJobs()
-  timer = setInterval(processJobs, intervalMs)
+  waTimer = setInterval(processWaJobs, waIntervalMs)
+  batchTimer = setInterval(processBatchJobs, batchIntervalMs)
 }
 
 const stopWorker = () => {
-  if (timer) clearInterval(timer)
-  logInfo('WA_WORKER', 'Stopped WA Background Worker')
+  if (waTimer) clearInterval(waTimer)
+  if (batchTimer) clearInterval(batchTimer)
+  logInfo('WORKER', 'Stopped Background Workers')
 }
 
 module.exports = {