From 0e06705a40ab1fed750482c179183e06013c724e Mon Sep 17 00:00:00 2001 From: The Nguyen <6950941+treoden@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:47:40 +0700 Subject: [PATCH] feat: Scheduled job implementation --- packages/evershop/bin/lib/cronjob.js | 49 +++++++++++++++++++ packages/evershop/bin/lib/startUp.js | 17 +++++++ packages/evershop/package.json | 1 + .../evershop/src/modules/base/bootstrap.js | 21 ++++++++ 4 files changed, 88 insertions(+) create mode 100644 packages/evershop/bin/lib/cronjob.js diff --git a/packages/evershop/bin/lib/cronjob.js b/packages/evershop/bin/lib/cronjob.js new file mode 100644 index 000000000..2b932f556 --- /dev/null +++ b/packages/evershop/bin/lib/cronjob.js @@ -0,0 +1,49 @@ +const cron = require('node-cron'); +const isResolvable = require('is-resolvable'); +const { getConfig } = require('@evershop/evershop/src/lib/util/getConfig'); +const { error } = require('@evershop/evershop/src/lib/log/logger'); + +module.exports = exports; + +function start() { + // Get the list of jobs from the configuration + const jobs = getConfig('system.jobs', []); + + const goodJobs = []; + jobs.forEach((job) => { + if (!isResolvable(job.resolve)) { + error( + `Job ${job.name} is not resolvable. Please check again the 'resolve' property.` + ); + } else if (!cron.validate(job.schedule)) { + error( + `Job ${job.name} has an invalid schedule. Please check again the 'schedule' property.` + ); + } else if (job.enabled === true) { + goodJobs.push(job); + } else { + error(`Job ${job.name} is disabled.`); + } + }); + // Schedule the jobs + goodJobs.forEach((job) => { + cron.schedule(job.schedule, async () => { + try { + // Load the module + const jobFunction = require(job.resolve); + // Make sure the module is a function or async function + if (typeof jobFunction !== 'function') { + throw new Error( + `Job ${job.name} is not a function. Make sure the module exports a function as default.` + ); + } + // Execute the job + await jobFunction(); + } catch (e) { + error(e); + } + }); + }); +} + +start(); diff --git a/packages/evershop/bin/lib/startUp.js b/packages/evershop/bin/lib/startUp.js index e4877eb65..6161f8ddb 100644 --- a/packages/evershop/bin/lib/startUp.js +++ b/packages/evershop/bin/lib/startUp.js @@ -86,6 +86,23 @@ module.exports.start = async function start(cb) { }); child.unref(); + + // Spawn the child process to manage scheduled jobs + const jobArgs = [path.resolve(__dirname, 'cronjob.js')]; + if (isDevelopmentMode() || process.argv.includes('--debug')) { + jobArgs.push('--debug'); + } + const jobChild = spawn('node', jobArgs, { + stdio: 'inherit', + env: { + ...process.env, + ALLOW_CONFIG_MUTATIONS: true + } + }); + jobChild.on('error', (err) => { + error(`Error spawning job processor: ${err}`); + }); + jobChild.unref(); }; module.exports.updateApp = function updateApp(cb) { diff --git a/packages/evershop/package.json b/packages/evershop/package.json index d8181ccb6..3a57a9bd4 100644 --- a/packages/evershop/package.json +++ b/packages/evershop/package.json @@ -97,6 +97,7 @@ "luxon": "^2.0.2", "mini-css-extract-plugin": "^2.6.1", "multer": "^1.4.2", + "node-cron": "^3.0.3", "npm": "^8.18.0", "ora": "^5.4.1", "pg": "^8.11.3", diff --git a/packages/evershop/src/modules/base/bootstrap.js b/packages/evershop/src/modules/base/bootstrap.js index b225919e9..82ec1137d 100644 --- a/packages/evershop/src/modules/base/bootstrap.js +++ b/packages/evershop/src/modules/base/bootstrap.js @@ -54,6 +54,27 @@ module.exports = async () => { required: ['name', 'enabled', 'resolve'] } }, + jobs: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' + }, + resolve: { + type: 'string' + }, + enabled: { + type: 'boolean' + }, + schedule: { + type: 'string' + } + }, + required: ['name', 'enabled', 'resolve', 'schedule'] + } + }, theme: { type: 'string' },