0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Prevented scheduling of recurring analytics jobs when not using emails (#12441)

no issue

- recurring jobs spin up worker threads which can be quite CPU intensive even when not performing much processing, this can be problematic in environments where there are many Ghost instances running
- updated the email job scheduling to be skipped on bootup when there are no emails in the database and to be started when the first email is created as long as we're not in testing env
- increase analytics job schedule from every 2 minutes to every 5 minutes to help spread the load further across instances
This commit is contained in:
Kevin Ansfield 2020-12-02 08:17:44 +00:00 committed by GitHub
parent 57c3244f3a
commit d675278b0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 15 deletions

View file

@ -10,7 +10,6 @@
require('./overrides'); require('./overrides');
const debug = require('ghost-ignition').debug('boot:init'); const debug = require('ghost-ignition').debug('boot:init');
const path = require('path');
const Promise = require('bluebird'); const Promise = require('bluebird');
const config = require('../shared/config'); const config = require('../shared/config');
const {events, i18n} = require('./lib/common'); const {events, i18n} = require('./lib/common');
@ -70,26 +69,15 @@ function initialiseServices() {
}); });
} }
function initializeRecurringJobs() { async function initializeRecurringJobs() {
// we don't want to kick off scheduled/recurring jobs that will interfere with tests // we don't want to kick off scheduled/recurring jobs that will interfere with tests
if (process.env.NODE_ENV.match(/^testing/)) { if (process.env.NODE_ENV.match(/^testing/)) {
return; return;
} }
const jobsService = require('./services/jobs');
if (config.get('backgroundJobs:emailAnalytics')) { if (config.get('backgroundJobs:emailAnalytics')) {
// use a random seconds value to avoid spikes to external APIs on the minute const emailAnalyticsJobs = require('./services/email-analytics/jobs');
const s = Math.floor(Math.random() * 60); // 0-59 await emailAnalyticsJobs.scheduleRecurringJobs();
// run every 2 minutes, either on 1,3,5... or 2,4,6...
const m = Math.floor(Math.random() * 2) + 1; // 1-2
jobsService.scheduleJob(
`${s} ${m}/2 * * * *`,
path.resolve(__dirname, 'services', 'email-analytics', 'jobs', 'fetch-latest.js'),
undefined,
'email-analytics-fetch-latest'
);
} }
} }

View file

@ -0,0 +1,38 @@
const path = require('path');
const config = require('../../../../shared/config');
const models = require('../../../models');
const jobsService = require('../../jobs');
let hasScheduled = false;
module.exports = {
async scheduleRecurringJobs() {
if (
!hasScheduled &&
config.get('backgroundJobs:emailAnalytics') &&
!process.env.NODE_ENV.match(/^testing/)
) {
// don't register email analytics job if we have no emails,
// processer usage from many sites spinning up threads can be high
const emailCount = await models.Email.count();
if (emailCount > 0) {
// use a random seconds value to avoid spikes to external APIs on the minute
const s = Math.floor(Math.random() * 60); // 0-59
// run every 5 minutes, on 1,6,11..., 2,7,12..., 3,8,13..., etc
const m = Math.floor(Math.random() * 5); // 0-4
jobsService.scheduleJob(
`${s} ${m}/5 * * * *`,
path.resolve(__dirname, 'fetch-latest.js'),
undefined,
'email-analytics-fetch-latest'
);
hasScheduled = true;
}
}
return hasScheduled;
}
};

View file

@ -220,6 +220,10 @@ async function pendingEmailHandler(emailModel, options) {
return; return;
} }
// make sure recurring background analytics jobs are running once we have emails
const emailAnalyticsJobs = require('../email-analytics/jobs');
emailAnalyticsJobs.scheduleRecurringJobs();
return jobService.addJob(sendEmailJob, {emailModel}); return jobService.addJob(sendEmailJob, {emailModel});
} }