From cd2e1f467b2473dd31a2303664bef1a5b4bc2495 Mon Sep 17 00:00:00 2001 From: cB-Guru-Sharan-Kumar-Ram Date: Wed, 26 Nov 2025 09:03:30 +0530 Subject: [PATCH] handle cron support to cluster [bin/www] --- .gitignore | 1 + app.js | 10 ------- bin/www | 67 +++++++++++++++++++++++++++++--------------- helper/cron-timer.js | 29 +++++++++++++++++++ init.js | 22 +++++++++++++++ package.json | 2 ++ 6 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 helper/cron-timer.js create mode 100644 init.js diff --git a/.gitignore b/.gitignore index 91747c2..f4a1547 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ public/ .env.development +package-lock.json diff --git a/app.js b/app.js index a51f143..096005e 100644 --- a/app.js +++ b/app.js @@ -19,7 +19,6 @@ const { console.log(process.env.NODE_ENV); const { v1 } = require("./routes"); -const sequelize = require("./config/db"); const app = express(); @@ -48,13 +47,4 @@ app.use((err, req, res) => { handleError(err, res); }); -sequelize - .sync() - .then(() => { - console.log("Database connected"); - }) - .catch(err => { - throw err; - }); - module.exports = app; diff --git a/bin/www b/bin/www index 662d6f3..a6b7cc7 100644 --- a/bin/www +++ b/bin/www @@ -1,5 +1,7 @@ #!/usr/bin/env node +require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` }); + /** * Module dependencies. */ @@ -9,55 +11,66 @@ const app = require("../app"); const debug = require("debug")("sidebrain:server"); const http = require("http"); const port = normalizePort(process.env.PORT || "3000"); +let server; /** * Get port from environment and store in Express. */ if (cluster.isMaster) { - console.log(`Master ${process.pid} is running`); - for (let i = 0; i < 1; i++) { + // Master initialization (DB, Cron, etc.) + const initMaster = require("../init"); + initMaster() + .then(() => { + console.log("✔ Master initialization completed"); + }) + .catch(err => { + console.error("❌ Master initialization failed:", err); + process.exit(1); + }); + + // Worker + const workers = + process.env.NODE_ENV === "stage" || process.env.NODE_ENV === "development" + ? 1 + : Math.max(1, cpu); + for (let i = 0; i < workers; i++) { + console.log("Forking worker", i + 1, "of", workers); cluster.fork(); } - cluster.on("exit", (worker, code, signal) => { - console.log(`worker ${worker.process.pid} died`); + + // Auto-restart worker on crash + cluster.on("exit", worker => { + console.log(`Worker ${worker.process.pid} died → restarting…`); + cluster.fork(); }); } else { - console.log(`Worker ${process.pid} started`); - app.set("port", port); /** * Create HTTP server. */ - - const server = http.createServer(app); + server = http.createServer(app); /** * Listen on provided port, on all network interfaces. */ + server.listen(port, () => { + console.log(`Worker ${process.pid} running`); + console.log(`Port : ${port}`); + console.log(`Env: ${process.env.NODE_ENV}`); + }); + server.keepAliveTimeout = 30000; - server.listen(port); server.on("error", onError); server.on("listening", onListening); - - /** - * Event listener for HTTP server "listening" event. - */ - - function onListening() { - var addr = server.address(); - var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; - debug("Listening on " + bind); - } } /** * Normalize a port into a number, string, or false. */ - function normalizePort(val) { - var port = parseInt(val, 10); + const port = parseInt(val, 10); if (isNaN(port)) { // named pipe @@ -75,13 +88,12 @@ function normalizePort(val) { /** * Event listener for HTTP server "error" event. */ - function onError(error) { if (error.syscall !== "listen") { throw error; } - var bind = typeof port === "string" ? "Pipe " + port : "Port " + port; + const bind = typeof port === "string" ? "Pipe " + port : "Port " + port; // handle specific listen errors with friendly messages switch (error.code) { @@ -97,3 +109,12 @@ function onError(error) { throw error; } } + +/** + * Event listener for HTTP server "listening" event. + */ +function onListening() { + const addr = server.address(); + const bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; + debug("Listening on " + bind); +} diff --git a/helper/cron-timer.js b/helper/cron-timer.js new file mode 100644 index 0000000..0930d85 --- /dev/null +++ b/helper/cron-timer.js @@ -0,0 +1,29 @@ +const cron = require("node-cron"); + +const sampleScheduledTask = async () => { + console.log(`[CRON Job] Execution started: ${new Date().toLocaleString()}`); + + try { + // --- Your scheduled logic goes here --- + console.log("Task successfully completed its job."); + } catch (error) { + console.error("An error occurred during scheduled task execution:", error); + } +}; + +// --- Setting the CRON Schedule --- + +// Format: second minute hour day-of-month month day-of-week +// * Second: 0-59 +// * Minute: 0-59 +// * Hour: 0-23 +// * Day-of-month: 1-31 +// * Month: 1-12 (or jan-dec) +// * Day-of-week: 0-7 (0 or 7 = Sunday, 1 = Monday) + +// Current Schedule: Run Every day, at exactly 12:00:00 AM (midnight). +cron.schedule(`0 0 0 * * *`, sampleScheduledTask); + +module.exports = { + sampleScheduledTask, +}; diff --git a/init.js b/init.js new file mode 100644 index 0000000..bbc4ccb --- /dev/null +++ b/init.js @@ -0,0 +1,22 @@ +const sequelize = require("./config/db"); +const { sampleScheduledTask } = require("./helper/cron-timer"); + +function initMaster() { + console.log("Master Initialization..."); + + return sequelize + .sync() + .then(() => { + console.log("Database connected"); + + // CRON Jobs + sampleScheduledTask(); + console.log("Cron jobs started"); + }) + .catch(err => { + console.error("❌ Database connection failed:", err.message); + throw err; + }); +} + +module.exports = initMaster; diff --git a/package.json b/package.json index eebf928..f21c66d 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,8 @@ "eslint-plugin-prettier": "^5.5.4", "husky": "^9.1.7", "lint-staged": "^16.2.7", + "node-cron": "^4.2.1", + "nodemon": "^3.1.11", "plop": "^3.1.1", "prettier": "^3.5.3" },