From d6080b2ea1cc0e117a65c8c330e153e6bfd9656d Mon Sep 17 00:00:00 2001
From: tuanh <tuan.hoangdinhanh@vn.bosch.com>
Date: Fri, 21 Mar 2025 10:30:56 +0700
Subject: [PATCH] feat(change-logs): add max size cap for change logs
 collection

---
 src/config/config.js                          |  3 ++
 src/index.js                                  |  5 ++-
 src/models/changeLog.model.js                 |  1 +
 src/scripts/convertLogsCap.js                 | 43 +++++++++++++++++++
 src/scripts/index.js                          |  3 ++
 ...eckVSSUpdate.js => setupScheduledCheck.js} |  0
 6 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 src/scripts/convertLogsCap.js
 create mode 100644 src/scripts/index.js
 rename src/scripts/{checkVSSUpdate.js => setupScheduledCheck.js} (100%)

diff --git a/src/config/config.js b/src/config/config.js
index 0ea9d6e..e662a84 100644
--- a/src/config/config.js
+++ b/src/config/config.js
@@ -59,6 +59,8 @@ const envVarsSchema = Joi.object()
     // Admin emails
     ADMIN_EMAILS: Joi.string().description('Admin emails'),
     ADMIN_PASSWORD: Joi.string().description('Admin password'),
+    // Change Logs max size
+    LOGS_MAX_SIZE: Joi.number().default(100).description('Max size of change logs in megabytes'),
   })
   .unknown();
 
@@ -178,6 +180,7 @@ const config = {
   },
   adminEmails: envVars.ADMIN_EMAILS?.split(',') || [],
   adminPassword: envVars.ADMIN_PASSWORD,
+  logsMaxSize: envVars.LOGS_MAX_SIZE,
 };
 
 if (config.env === 'development') {
diff --git a/src/index.js b/src/index.js
index c79d6ce..299a17a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -4,12 +4,13 @@ const config = require('./config/config');
 const logger = require('./config/logger');
 const initializeRoles = require('./utils/initializeRoles');
 const { init } = require('./config/socket');
-const setupScheduledCheck = require('./scripts/checkVSSUpdate');
-const assignAdmins = require('./scripts/assignAdmins');
+const { setupScheduledCheck, assignAdmins, convertLogsCap } = require('./scripts');
 
 let server;
 mongoose.connect(config.mongoose.url, config.mongoose.options).then(() => {
   logger.info('Connected to MongoDB ');
+
+  convertLogsCap();
   initializeRoles().then(() => assignAdmins());
   server = app.listen(config.port, () => {
     logger.info(`Listening to port ${config.port}`);
diff --git a/src/models/changeLog.model.js b/src/models/changeLog.model.js
index 6d34fd3..979f17e 100644
--- a/src/models/changeLog.model.js
+++ b/src/models/changeLog.model.js
@@ -46,6 +46,7 @@ const changeLogSchema = new mongoose.Schema(
 
 changeLogSchema.plugin(toJSON);
 changeLogSchema.plugin(paginate);
+changeLogSchema.index({ ref: 1 });
 
 const ChangeLog = mongoose.model('ChangeLog', changeLogSchema);
 
diff --git a/src/scripts/convertLogsCap.js b/src/scripts/convertLogsCap.js
new file mode 100644
index 0000000..d4eda67
--- /dev/null
+++ b/src/scripts/convertLogsCap.js
@@ -0,0 +1,43 @@
+const mongoose = require('mongoose');
+const logger = require('../config/logger');
+const config = require('../config/config');
+const ChangeLog = require('../models/changeLog.model');
+
+async function setLogsCap() {
+  const db = mongoose.connection.db;
+  const name = 'changelogs';
+  const max = config.logsMaxSize * 1024 * 1024; // 100MB capped
+
+  try {
+    const collInfo = await db.listCollections({ name }).next();
+
+    if (!collInfo) {
+      await db.createCollection(name, { capped: true, size: max });
+      return logger.info(`Created capped collection ${name} with ${max} bytes`);
+    }
+
+    const stats = await db.collection(name).stats();
+    if (stats.capped && stats.maxSize === max) {
+      return logger.info(`Collection ${name} is already capped to ${max} bytes. Skipping...`);
+    }
+
+    await db.command({
+      convertToCapped: name,
+      size: max,
+    });
+    logger.info(`Capped collection ${name} to ${max} bytes`);
+  } catch (error) {
+    logger.error(`Error capping collection ${name}: %o`, error?.message || error);
+  }
+}
+
+async function convertLogsCap() {
+  try {
+    await setLogsCap();
+    await ChangeLog.createIndexes();
+  } catch (error) {
+    logger.error('Error converting logs cap: %o', error.message || error);
+  }
+}
+
+module.exports = convertLogsCap;
diff --git a/src/scripts/index.js b/src/scripts/index.js
new file mode 100644
index 0000000..120605c
--- /dev/null
+++ b/src/scripts/index.js
@@ -0,0 +1,3 @@
+module.exports.assignAdmins = require('./assignAdmins');
+module.exports.setupScheduledCheck = require('./setupScheduledCheck');
+module.exports.convertLogsCap = require('./convertLogsCap');
diff --git a/src/scripts/checkVSSUpdate.js b/src/scripts/setupScheduledCheck.js
similarity index 100%
rename from src/scripts/checkVSSUpdate.js
rename to src/scripts/setupScheduledCheck.js
-- 
GitLab