diff --git a/ghost/job-manager/test/job-manager.test.js b/ghost/job-manager/test/job-manager.test.js index e9a5fc9d2a..7a6df327ee 100644 --- a/ghost/job-manager/test/job-manager.test.js +++ b/ghost/job-manager/test/job-manager.test.js @@ -266,120 +266,122 @@ describe('Job Manager', function () { } }); - it('adds job to the queue when it is a unique one', async function () { - const spy = sinon.spy(); - const JobModel = { - findOne: sinon.stub().resolves(undefined), - add: sinon.stub().resolves() - }; + describe('Offloaded jobs', function () { + it('adds job to the queue when it is a unique one', async function () { + const spy = sinon.spy(); + const JobModel = { + findOne: sinon.stub().resolves(undefined), + add: sinon.stub().resolves() + }; - const jobManager = new JobManager({JobModel}); - await jobManager.addOneOffJob({ - job: spy, - name: 'unique name', - data: 'test data' - }); - - assert.equal(JobModel.add.called, true); - }); - - it('does not add a job to the queue when it already exists', async function () { - const spy = sinon.spy(); - const JobModel = { - findOne: sinon.stub().resolves({name: 'I am the only one'}), - add: sinon.stub().throws('should not be called') - }; - - const jobManager = new JobManager({JobModel}); - - try { + const jobManager = new JobManager({JobModel}); await jobManager.addOneOffJob({ job: spy, - name: 'I am the only one', + name: 'unique name', data: 'test data' }); - throw new Error('should not reach this point'); - } catch (error) { - assert.equal(error.message, 'A "I am the only one" one off job has already been executed.'); - } - }); - it('sets a finished state on a job', async function () { - const JobModel = { - findOne: sinon.stub() - .onCall(0) - .resolves(null) - .resolves({id: 'unique', name: 'successful-oneoff'}), - add: sinon.stub().resolves({name: 'successful-oneoff'}), - edit: sinon.stub().resolves({name: 'successful-oneoff'}) - }; - - const jobManager = new JobManager({JobModel}); - - jobManager.addOneOffJob({ - job: path.resolve(__dirname, './jobs/message.js'), - name: 'successful-oneoff' + assert.equal(JobModel.add.called, true); }); - // allow job to get picked up and executed - await delay(100); + it('does not add a job to the queue when it already exists', async function () { + const spy = sinon.spy(); + const JobModel = { + findOne: sinon.stub().resolves({name: 'I am the only one'}), + add: sinon.stub().throws('should not be called') + }; - jobManager.bree.workers['successful-oneoff'].postMessage('be done!'); + const jobManager = new JobManager({JobModel}); - // allow the message to be passed around - await delay(100); - - // tracks the job start - should(JobModel.edit.args[0][0].status).equal('started'); - should(JobModel.edit.args[0][0].started_at).not.equal(undefined); - should(JobModel.edit.args[0][1].id).equal('unique'); - - // tracks the job finish - should(JobModel.edit.args[1][0].status).equal('finished'); - should(JobModel.edit.args[1][0].finished_at).not.equal(undefined); - should(JobModel.edit.args[1][1].id).equal('unique'); - }); - - it('sets a failed state on a job', async function () { - const JobModel = { - findOne: sinon.stub() - .onCall(0) - .resolves(null) - .resolves({id: 'unique', name: 'failed-oneoff'}), - add: sinon.stub().resolves({name: 'failed-oneoff'}), - edit: sinon.stub().resolves({name: 'failed-oneoff'}) - }; - - let job = function namedJob() { - throw new Error('job error'); - }; - const spyHandler = sinon.spy(); - const jobManager = new JobManager({errorHandler: spyHandler, JobModel}); - - jobManager.addOneOffJob({ - job, - name: 'failed-oneoff' + try { + await jobManager.addOneOffJob({ + job: spy, + name: 'I am the only one', + data: 'test data' + }); + throw new Error('should not reach this point'); + } catch (error) { + assert.equal(error.message, 'A "I am the only one" one off job has already been executed.'); + } }); - // give time to execute the job - // has to be this long because in Node v10 the communication is - // done through processes, which takes longer comparing to worker_threads - // can be reduced to 100 when Node v10 support is dropped - await delay(100); + it('sets a finished state on a job', async function () { + const JobModel = { + findOne: sinon.stub() + .onCall(0) + .resolves(null) + .resolves({id: 'unique', name: 'successful-oneoff'}), + add: sinon.stub().resolves({name: 'successful-oneoff'}), + edit: sinon.stub().resolves({name: 'successful-oneoff'}) + }; - // still calls the original error handler - should(spyHandler.called).be.true(); - should(spyHandler.args[0][0].message).equal('job error'); - should(spyHandler.args[0][1].name).equal('failed-oneoff'); + const jobManager = new JobManager({JobModel}); - // tracks the job start - should(JobModel.edit.args[0][0].status).equal('started'); - should(JobModel.edit.args[0][0].started_at).not.equal(undefined); - should(JobModel.edit.args[0][1].id).equal('unique'); + jobManager.addOneOffJob({ + job: path.resolve(__dirname, './jobs/message.js'), + name: 'successful-oneoff' + }); - // tracks the job failure - should(JobModel.edit.args[1][0].status).equal('failed'); - should(JobModel.edit.args[1][1].id).equal('unique'); + // allow job to get picked up and executed + await delay(100); + + jobManager.bree.workers['successful-oneoff'].postMessage('be done!'); + + // allow the message to be passed around + await delay(100); + + // tracks the job start + should(JobModel.edit.args[0][0].status).equal('started'); + should(JobModel.edit.args[0][0].started_at).not.equal(undefined); + should(JobModel.edit.args[0][1].id).equal('unique'); + + // tracks the job finish + should(JobModel.edit.args[1][0].status).equal('finished'); + should(JobModel.edit.args[1][0].finished_at).not.equal(undefined); + should(JobModel.edit.args[1][1].id).equal('unique'); + }); + + it('sets a failed state on a job', async function () { + const JobModel = { + findOne: sinon.stub() + .onCall(0) + .resolves(null) + .resolves({id: 'unique', name: 'failed-oneoff'}), + add: sinon.stub().resolves({name: 'failed-oneoff'}), + edit: sinon.stub().resolves({name: 'failed-oneoff'}) + }; + + let job = function namedJob() { + throw new Error('job error'); + }; + const spyHandler = sinon.spy(); + const jobManager = new JobManager({errorHandler: spyHandler, JobModel}); + + jobManager.addOneOffJob({ + job, + name: 'failed-oneoff' + }); + + // give time to execute the job + // has to be this long because in Node v10 the communication is + // done through processes, which takes longer comparing to worker_threads + // can be reduced to 100 when Node v10 support is dropped + await delay(100); + + // still calls the original error handler + should(spyHandler.called).be.true(); + should(spyHandler.args[0][0].message).equal('job error'); + should(spyHandler.args[0][1].name).equal('failed-oneoff'); + + // tracks the job start + should(JobModel.edit.args[0][0].status).equal('started'); + should(JobModel.edit.args[0][0].started_at).not.equal(undefined); + should(JobModel.edit.args[0][1].id).equal('unique'); + + // tracks the job failure + should(JobModel.edit.args[1][0].status).equal('failed'); + should(JobModel.edit.args[1][1].id).equal('unique'); + }); }); });