diff --git a/ghost/core/core/boot.js b/ghost/core/core/boot.js index 3be81d2b25..b56ed128c6 100644 --- a/ghost/core/core/boot.js +++ b/ghost/core/core/boot.js @@ -132,6 +132,19 @@ async function initCore({ghostServer, config, bootLogger, frontend}) { }); debug('End: Job Service'); + // Mentions Job Service allows mentions to be processed in the background + debug('Begin: Mentions Job Service'); + const mentionsJobService = require('./server/services/mentions-jobs'); + + if (config.get('server:testmode')) { + mentionsJobService.initTestMode(); + } + + ghostServer.registerCleanupTask(async () => { + await mentionsJobService.shutdown(); + }); + debug('End: Mentions Job Service'); + ghostServer.registerCleanupTask(async () => { await urlService.shutdown(); }); diff --git a/ghost/core/core/server/services/mentions-jobs/index.js b/ghost/core/core/server/services/mentions-jobs/index.js new file mode 100644 index 0000000000..e761b6e7b0 --- /dev/null +++ b/ghost/core/core/server/services/mentions-jobs/index.js @@ -0,0 +1 @@ +module.exports = require('./job-service'); diff --git a/ghost/core/core/server/services/mentions-jobs/job-service.js b/ghost/core/core/server/services/mentions-jobs/job-service.js new file mode 100644 index 0000000000..3b8298e73c --- /dev/null +++ b/ghost/core/core/server/services/mentions-jobs/job-service.js @@ -0,0 +1,48 @@ +/** + * Minimal wrapper around our external lib + * Intended for passing any Ghost internals such as logging and config + */ + +const JobManager = require('@tryghost/job-manager'); +const logging = require('@tryghost/logging'); +const models = require('../../models'); +const sentry = require('../../../shared/sentry'); +const domainEvents = require('@tryghost/domain-events'); + +const errorHandler = (error, workerMeta) => { + logging.info(`Capturing error for worker during execution of job: ${workerMeta.name}`); + logging.error(error); + sentry.captureException(error); +}; + +const workerMessageHandler = ({name, message}) => { + if (typeof message === 'string') { + logging.info(`Worker for job ${name} sent a message: ${message}`); + } +}; + +const initTestMode = () => { + // Output job queue length every 5 seconds + setInterval(() => { + logging.warn(`${jobManager.queue.length()} jobs in the queue. Idle: ${jobManager.queue.idle()}`); + + const runningScheduledjobs = Object.keys(jobManager.bree.workers); + if (Object.keys(jobManager.bree.workers).length) { + logging.warn(`${Object.keys(jobManager.bree.workers).length} jobs running: ${runningScheduledjobs}`); + } + + const scheduledJobs = Object.keys(jobManager.bree.intervals); + if (Object.keys(jobManager.bree.intervals).length) { + logging.warn(`${Object.keys(jobManager.bree.intervals).length} scheduled jobs: ${scheduledJobs}`); + } + + if (runningScheduledjobs.length === 0 && scheduledJobs.length === 0) { + logging.warn('No scheduled or running jobs'); + } + }, 5000); +}; + +const jobManager = new JobManager({errorHandler, workerMessageHandler, JobModel: models.Job, domainEvents}); + +module.exports = jobManager; +module.exports.initTestMode = initTestMode; diff --git a/ghost/core/core/server/services/mentions/service.js b/ghost/core/core/server/services/mentions/service.js index 592ab36909..714d805d4e 100644 --- a/ghost/core/core/server/services/mentions/service.js +++ b/ghost/core/core/server/services/mentions/service.js @@ -16,7 +16,7 @@ const outputSerializerUrlUtil = require('../../../server/api/endpoints/utils/ser const urlService = require('../url'); const settingsCache = require('../../../shared/settings-cache'); const DomainEvents = require('@tryghost/domain-events'); -const jobsService = require('../jobs'); +const jobsService = require('../mentions-jobs'); function getPostUrl(post) { const jsonModel = {}; diff --git a/ghost/core/test/e2e-api/webmentions/webmentions.test.js b/ghost/core/test/e2e-api/webmentions/webmentions.test.js index 2085393a2c..37b22bb2e3 100644 --- a/ghost/core/test/e2e-api/webmentions/webmentions.test.js +++ b/ghost/core/test/e2e-api/webmentions/webmentions.test.js @@ -9,7 +9,7 @@ const models = require('../../../core/server/models'); const assert = require('assert'); const urlUtils = require('../../../core/shared/url-utils'); const nock = require('nock'); -const jobsService = require('../../../core/server/services/jobs'); +const jobsService = require('../../../core/server/services/mentions-jobs'); const DomainEvents = require('@tryghost/domain-events'); describe('Webmentions (receiving)', function () { diff --git a/ghost/core/test/e2e-server/services/mentions.test.js b/ghost/core/test/e2e-server/services/mentions.test.js index 7ea2cb5da7..92de47227f 100644 --- a/ghost/core/test/e2e-server/services/mentions.test.js +++ b/ghost/core/test/e2e-server/services/mentions.test.js @@ -4,7 +4,7 @@ const nock = require('nock'); const assert = require('assert'); const markdownToMobiledoc = require('../../utils/fixtures/data-generator').markdownToMobiledoc; const dnsPromises = require('dns').promises; -const jobsService = require('../../../core/server/services/jobs'); +const jobsService = require('../../../core/server/services/mentions-jobs'); let agent; let mentionUrl = new URL('https://www.otherghostsite.com/');