diff --git a/core/server/api/canary/members.js b/core/server/api/canary/members.js index 174f1f4df2..1299b35949 100644 --- a/core/server/api/canary/members.js +++ b/core/server/api/canary/members.js @@ -371,28 +371,31 @@ module.exports = { }; } else { const emailRecipient = frame.user.get('email'); - jobsService.addJob(async () => { - const result = await membersService.importer.perform(job.id); - const importLabelModel = result.imported ? await models.Label.findOne(importLabel) : null; - const emailContent = membersService.importer.generateCompletionEmail(result, { - emailRecipient, - importLabel: importLabelModel ? importLabelModel.toJSON() : null - }); - const errorCSV = membersService.importer.generateErrorCSV(result); - const emailSubject = result.imported > 0 ? 'Your member import is complete' : 'Your member import was unsuccessful'; + jobsService.addJob({ + job: async () => { + const result = await membersService.importer.perform(job.id); + const importLabelModel = result.imported ? await models.Label.findOne(importLabel) : null; + const emailContent = membersService.importer.generateCompletionEmail(result, { + emailRecipient, + importLabel: importLabelModel ? importLabelModel.toJSON() : null + }); + const errorCSV = membersService.importer.generateErrorCSV(result); + const emailSubject = result.imported > 0 ? 'Your member import is complete' : 'Your member import was unsuccessful'; - await ghostMailer.send({ - to: emailRecipient, - subject: emailSubject, - html: emailContent, - forceTextContent: true, - attachments: [{ - filename: `${importLabel.name} - Errors.csv`, - contents: errorCSV, - contentType: 'text/csv', - contentDisposition: 'attachment' - }] - }); + await ghostMailer.send({ + to: emailRecipient, + subject: emailSubject, + html: emailContent, + forceTextContent: true, + attachments: [{ + filename: `${importLabel.name} - Errors.csv`, + contents: errorCSV, + contentType: 'text/csv', + contentDisposition: 'attachment' + }] + }); + }, + offloaded: false }); return {}; diff --git a/core/server/services/email-analytics/jobs/index.js b/core/server/services/email-analytics/jobs/index.js index 20c674ddc5..d001273c67 100644 --- a/core/server/services/email-analytics/jobs/index.js +++ b/core/server/services/email-analytics/jobs/index.js @@ -27,12 +27,11 @@ module.exports = { // 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' - ); + jobsService.addJob({ + at: `${s} ${m}/5 * * * *`, + job: path.resolve(__dirname, 'fetch-latest.js'), + name: 'email-analytics-fetch-latest' + }); hasScheduled = true; } diff --git a/core/server/services/mega/mega.js b/core/server/services/mega/mega.js index 91a98a0e71..ec9c6cd765 100644 --- a/core/server/services/mega/mega.js +++ b/core/server/services/mega/mega.js @@ -10,7 +10,7 @@ const logging = require('../../../shared/logging'); const settingsCache = require('../settings/cache'); const membersService = require('../members'); const bulkEmailService = require('../bulk-email'); -const jobService = require('../jobs'); +const jobsService = require('../jobs'); const db = require('../../data/db'); const models = require('../../models'); const postEmailSerializer = require('./post-email-serializer'); @@ -225,7 +225,11 @@ async function pendingEmailHandler(emailModel, options) { const emailAnalyticsJobs = require('../email-analytics/jobs'); emailAnalyticsJobs.scheduleRecurringJobs(); - return jobService.addJob(sendEmailJob, {emailModel}); + return jobsService.addJob({ + job: sendEmailJob, + data: {emailModel}, + offloaded: false + }); } async function sendEmailJob({emailModel, options}) { diff --git a/core/server/web/api/testmode/index.js b/core/server/web/api/testmode/index.js index 0479369ddf..0c94b40dd6 100644 --- a/core/server/web/api/testmode/index.js +++ b/core/server/web/api/testmode/index.js @@ -1,7 +1,7 @@ const path = require('path'); const logging = require('../../../../shared/logging'); const express = require('../../../../shared/express'); -const jobService = require('../../../services/jobs'); +const jobsService = require('../../../services/jobs'); /** A bunch of helper routes for testing purposes */ module.exports = function testRoutes() { @@ -28,14 +28,17 @@ module.exports = function testRoutes() { const timeout = req.params.timeout * 1000; logging.info('Create Slow Job with timeout of', timeout); - jobService.addJob(() => { - return new Promise((resolve) => { - logging.info('Start Slow Job'); - setTimeout(() => { - logging.info('End Slow Job', timeout); - resolve(); - }, timeout); - }); + jobsService.addJob({ + job: () => { + return new Promise((resolve) => { + logging.info('Start Slow Job'); + setTimeout(() => { + logging.info('End Slow Job', timeout); + resolve(); + }, timeout); + }); + }, + offloaded: false }); res.sendStatus(202); @@ -47,22 +50,28 @@ module.exports = function testRoutes() { } const schedule = req.params.schedule; + const jobName = req.params.name || `generic-${new Date().getTime()}`; logging.info('Achedule a Job with schedule of:', schedule, req.params.name); if (req.params.name) { const jobPath = path.resolve(__dirname, 'jobs', `${req.params.name}.js`); - jobService.scheduleJob(schedule, jobPath); + jobsService.addJob({ + at: schedule, + job: jobPath, + name: jobName + }); } else { - jobService.scheduleJob(schedule, () => { - return new Promise((resolve) => { - logging.info('Start scheduled Job'); - - setTimeout(() => { - logging.info('End scheduled Job run', schedule); - resolve(); - }, 20 * 1000); - }); - }, {}); + jobsService.addJob({ + at: schedule, + job: () => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, 20 * 1000); + }); + }, + name: jobName + }); } res.sendStatus(202); diff --git a/package.json b/package.json index 9c7c930b99..c87e1354f8 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@tryghost/errors": "0.2.6", "@tryghost/helpers": "1.1.35", "@tryghost/image-transform": "1.0.3", - "@tryghost/job-manager": "0.6.0", + "@tryghost/job-manager": "0.7.0", "@tryghost/kg-card-factory": "2.1.4", "@tryghost/kg-default-atoms": "2.0.2", "@tryghost/kg-default-cards": "3.0.1", diff --git a/yarn.lock b/yarn.lock index 63e7365229..dfdc49ebfa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -457,16 +457,16 @@ optionalDependencies: sharp "0.25.4" -"@tryghost/job-manager@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@tryghost/job-manager/-/job-manager-0.6.0.tgz#5023f4b37577ac6966bba3608896948f2d030004" - integrity sha512-kZh3sAexCkP4WghIskB6ZAJQap8KQWDtcLWRXTzCL1fO6BzOstJgw4gvRMDb2t8peUHhwf34fKbeIKecl5cv0g== +"@tryghost/job-manager@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@tryghost/job-manager/-/job-manager-0.7.0.tgz#ddc193580778d5c46a7dab5affa74abca7d029f3" + integrity sha512-m1b7qyEzssa2YeoRtXV5Q2acHp+HUEXquzVgi1yGoxAw6dU994z6MIYPq8JpDTR2XnY2Tw2mghlVfgBQ995sFg== dependencies: "@breejs/later" "4.0.2" bree "4.1.0" - cron-validate "1.4.1" - fastq "1.9.0" - p-wait-for "3.1.0" + cron-validate "1.4.2" + fastq "1.10.0" + p-wait-for "3.2.0" "@tryghost/kg-card-factory@2.1.4": version "2.1.4" @@ -751,6 +751,11 @@ dependencies: "@types/node" "*" +"@types/lodash@^4.14.165": + version "4.14.167" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.167.tgz#ce7d78553e3c886d4ea643c37ec7edc20f16765e" + integrity sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw== + "@types/mime@*": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" @@ -2259,7 +2264,14 @@ create-error@~0.3.1: resolved "https://registry.yarnpkg.com/create-error/-/create-error-0.3.1.tgz#69810245a629e654432bf04377360003a5351a23" integrity sha1-aYECRaYp5lRDK/BDdzYAA6U1GiM= -cron-validate@1.4.1, cron-validate@^1.4.1: +cron-validate@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/cron-validate/-/cron-validate-1.4.2.tgz#1ecf9a5689e5697d17c2337bbfd8606bed7d441e" + integrity sha512-GdjNeiZjNA9u6BItfhnd1MFPbT86wmJ2/2BwDQyXZY0mb9nhLSeh3PVKk7G185qfUSwbtGNtCLrKI/9pclvGrg== + dependencies: + yup "0.32.8" + +cron-validate@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/cron-validate/-/cron-validate-1.4.1.tgz#d637f677a2f5fa37ed61d265a17af502b02b12d6" integrity sha512-83VZ6/I52ybU8lwvrAgjnwR70/1pl867pgE4LbzO+ha+rZOmNMRqMm8vVG9s7a2fpnBQR6/+F7oRiGVfnC+9Ug== @@ -3554,10 +3566,10 @@ fast-safe-stringify@^2.0.7: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== -fastq@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" - integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== +fastq@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb" + integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA== dependencies: reusify "^1.0.4" @@ -6533,6 +6545,11 @@ nan@^2.12.1, nan@^2.14.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== +nanoclone@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" + integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== + nanoid@3.1.12, nanoid@^3.1.12: version "3.1.12" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" @@ -7114,6 +7131,13 @@ p-wait-for@3.1.0: dependencies: p-timeout "^3.0.0" +p-wait-for@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-wait-for/-/p-wait-for-3.2.0.tgz#640429bcabf3b0dd9f492c31539c5718cb6a3f1f" + integrity sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA== + dependencies: + p-timeout "^3.0.0" + pac-proxy-agent@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz#115b1e58f92576cac2eba718593ca7b0e37de2ad" @@ -10069,6 +10093,19 @@ yup@0.30.0: property-expr "^2.0.4" toposort "^2.0.2" +yup@0.32.8: + version "0.32.8" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.8.tgz#16e4a949a86a69505abf99fd0941305ac9adfc39" + integrity sha512-SZulv5FIZ9d5H99EN5tRCRPXL0eyoYxWIP1AacCrjC9d4DfP13J1dROdKGfpfRHT3eQB6/ikBl5jG21smAfCkA== + dependencies: + "@babel/runtime" "^7.10.5" + "@types/lodash" "^4.14.165" + lodash "^4.17.20" + lodash-es "^4.17.11" + nanoclone "^0.2.1" + property-expr "^2.0.4" + toposort "^2.0.2" + zip-stream@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04"