2020-11-05 06:39:51 +03:00
|
|
|
// Switch these lines once there are useful utils
|
|
|
|
// const testUtils = require('./utils');
|
|
|
|
require('./utils');
|
2022-07-21 21:39:54 +03:00
|
|
|
const assert = require('assert');
|
2020-11-19 07:58:41 +03:00
|
|
|
const path = require('path');
|
2020-11-10 06:35:04 +03:00
|
|
|
const sinon = require('sinon');
|
|
|
|
const delay = require('delay');
|
2020-12-02 11:26:15 +03:00
|
|
|
const FakeTimers = require('@sinonjs/fake-timers');
|
2021-12-02 15:48:48 +03:00
|
|
|
const logging = require('@tryghost/logging');
|
2020-11-05 06:39:51 +03:00
|
|
|
|
2020-11-10 06:35:04 +03:00
|
|
|
const JobManager = require('../index');
|
2020-11-05 06:39:51 +03:00
|
|
|
|
2021-12-02 15:48:48 +03:00
|
|
|
const sandbox = sinon.createSandbox();
|
2020-11-10 07:11:24 +03:00
|
|
|
|
2021-12-02 15:48:48 +03:00
|
|
|
describe('Job Manager', function () {
|
2020-11-10 07:15:08 +03:00
|
|
|
beforeEach(function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
sandbox.stub(logging, 'info');
|
|
|
|
sandbox.stub(logging, 'warn');
|
|
|
|
sandbox.stub(logging, 'error');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
sandbox.restore();
|
2020-11-10 07:11:24 +03:00
|
|
|
});
|
|
|
|
|
2020-11-05 06:39:51 +03:00
|
|
|
it('public interface', function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2020-11-05 06:39:51 +03:00
|
|
|
|
|
|
|
should.exist(jobManager.addJob);
|
2020-11-05 07:36:29 +03:00
|
|
|
});
|
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
describe('Add a job', function () {
|
|
|
|
describe('Inline jobs', function () {
|
|
|
|
it('adds a job to a queue', async function () {
|
|
|
|
const spy = sinon.spy();
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2020-11-10 06:35:04 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
job: spy,
|
|
|
|
data: 'test data',
|
|
|
|
offloaded: false
|
|
|
|
});
|
|
|
|
should(jobManager.queue.idle()).be.false();
|
|
|
|
|
|
|
|
// give time to execute the job
|
|
|
|
await delay(1);
|
|
|
|
|
|
|
|
should(jobManager.queue.idle()).be.true();
|
|
|
|
should(spy.called).be.true();
|
|
|
|
should(spy.args[0][0]).equal('test data');
|
2021-01-06 03:45:23 +03:00
|
|
|
});
|
2020-11-10 06:35:04 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
it('handles failed job gracefully', async function () {
|
|
|
|
const spy = sinon.stub().throws();
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2020-11-10 06:35:04 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
job: spy,
|
|
|
|
data: 'test data',
|
|
|
|
offloaded: false
|
|
|
|
});
|
2022-07-21 20:56:17 +03:00
|
|
|
should(jobManager.queue.idle()).be.false();
|
2020-11-10 07:11:24 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
// give time to execute the job
|
|
|
|
await delay(1);
|
2020-11-10 07:11:24 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.queue.idle()).be.true();
|
|
|
|
should(spy.called).be.true();
|
|
|
|
should(spy.args[0][0]).equal('test data');
|
|
|
|
should(logging.error.called).be.true();
|
2021-01-06 03:45:23 +03:00
|
|
|
});
|
2021-01-06 03:46:47 +03:00
|
|
|
});
|
2020-11-10 07:11:24 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
describe('Offloaded jobs', function () {
|
2022-07-21 20:56:17 +03:00
|
|
|
it('fails to schedule for invalid scheduling expression', function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2021-01-06 03:46:47 +03:00
|
|
|
|
|
|
|
try {
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
at: 'invalid expression',
|
|
|
|
name: 'jobName'
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
err.message.should.equal('Invalid schedule format');
|
|
|
|
}
|
|
|
|
});
|
2020-11-10 07:11:24 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
it('fails to schedule for no job name', function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2021-01-06 03:46:47 +03:00
|
|
|
|
|
|
|
try {
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
at: 'invalid expression',
|
|
|
|
job: () => {}
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
err.message.should.equal('Name parameter should be present if job is a function');
|
|
|
|
}
|
|
|
|
});
|
2020-11-10 06:35:04 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
it('schedules a job using date format', async function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2021-01-06 03:46:47 +03:00
|
|
|
const timeInTenSeconds = new Date(Date.now() + 10);
|
|
|
|
const jobPath = path.resolve(__dirname, './jobs/simple.js');
|
2020-11-05 07:36:29 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
const clock = FakeTimers.install({now: Date.now()});
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
at: timeInTenSeconds,
|
|
|
|
job: jobPath,
|
|
|
|
name: 'job-in-ten'
|
2021-01-06 03:45:23 +03:00
|
|
|
});
|
2020-11-19 07:58:41 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.timeouts['job-in-ten']).type('object');
|
|
|
|
should(jobManager.bree.workers['job-in-ten']).type('undefined');
|
2020-11-19 07:58:41 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
// allow to run the job and start the worker
|
|
|
|
await clock.nextAsync();
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.workers['job-in-ten']).type('object');
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
const promise = new Promise((resolve, reject) => {
|
|
|
|
jobManager.bree.workers['job-in-ten'].on('error', reject);
|
|
|
|
jobManager.bree.workers['job-in-ten'].on('exit', (code) => {
|
|
|
|
should(code).equal(0);
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
});
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
// allow job to finish execution and exit
|
|
|
|
clock.next();
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
await promise;
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.workers['job-in-ten']).type('undefined');
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
clock.uninstall();
|
2020-12-02 11:26:15 +03:00
|
|
|
});
|
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
it('schedules a job to run immediately', async function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2021-01-06 03:46:47 +03:00
|
|
|
const clock = FakeTimers.install({now: Date.now()});
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
const jobPath = path.resolve(__dirname, './jobs/simple.js');
|
|
|
|
jobManager.addJob({
|
|
|
|
job: jobPath,
|
|
|
|
name: 'job-now'
|
|
|
|
});
|
2020-12-02 11:26:15 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.timeouts['job-now']).type('object');
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
// allow scheduler to pick up the job
|
|
|
|
clock.tick(1);
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.workers['job-now']).type('object');
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
const promise = new Promise((resolve, reject) => {
|
|
|
|
jobManager.bree.workers['job-now'].on('error', reject);
|
|
|
|
jobManager.bree.workers['job-now'].on('exit', (code) => {
|
|
|
|
should(code).equal(0);
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
});
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
await promise;
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.workers['job-now']).type('undefined');
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
clock.uninstall();
|
2020-12-09 09:11:11 +03:00
|
|
|
});
|
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
it('fails to schedule a job with the same name to run immediately one after another', async function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2022-07-21 20:56:17 +03:00
|
|
|
const clock = FakeTimers.install({now: Date.now()});
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
const jobPath = path.resolve(__dirname, './jobs/simple.js');
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
job: jobPath,
|
2022-07-21 20:56:17 +03:00
|
|
|
name: 'job-now'
|
2021-01-06 03:46:47 +03:00
|
|
|
});
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
should(jobManager.bree.timeouts['job-now']).type('object');
|
|
|
|
|
|
|
|
// allow scheduler to pick up the job
|
|
|
|
clock.tick(1);
|
|
|
|
|
|
|
|
should(jobManager.bree.workers['job-now']).type('object');
|
|
|
|
|
|
|
|
const promise = new Promise((resolve, reject) => {
|
|
|
|
jobManager.bree.workers['job-now'].on('error', reject);
|
|
|
|
jobManager.bree.workers['job-now'].on('exit', (code) => {
|
|
|
|
should(code).equal(0);
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
await promise;
|
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(jobManager.bree.workers['job-now']).type('undefined');
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
(() => {
|
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
job: jobPath,
|
|
|
|
name: 'job-now'
|
|
|
|
});
|
2022-07-21 20:56:17 +03:00
|
|
|
}).should.throw('Job #1 has a duplicate job name of job-now');
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
clock.uninstall();
|
2021-01-06 03:46:47 +03:00
|
|
|
});
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
it('uses custom error handler when job fails', async function (){
|
|
|
|
let job = function namedJob() {
|
|
|
|
throw new Error('job error');
|
|
|
|
};
|
|
|
|
const spyHandler = sinon.spy();
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({errorHandler: spyHandler});
|
2020-12-09 09:11:11 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:46:47 +03:00
|
|
|
job,
|
|
|
|
name: 'will-fail'
|
2021-01-06 03:45:23 +03:00
|
|
|
});
|
2020-12-07 06:50:41 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
// 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(600);
|
2020-12-07 06:50:41 +03:00
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
should(spyHandler.called).be.true();
|
|
|
|
should(spyHandler.args[0][0].message).equal('job error');
|
|
|
|
should(spyHandler.args[0][1].name).equal('will-fail');
|
2021-01-06 03:45:23 +03:00
|
|
|
});
|
2021-02-22 09:10:47 +03:00
|
|
|
|
|
|
|
it('uses worker message handler when job sends a message', async function (){
|
|
|
|
const workerMessageHandlerSpy = sinon.spy();
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({workerMessageHandler: workerMessageHandlerSpy});
|
2021-02-22 09:10:47 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-02-22 09:10:47 +03:00
|
|
|
job: path.resolve(__dirname, './jobs/message.js'),
|
|
|
|
name: 'will-send-msg'
|
|
|
|
});
|
|
|
|
jobManager.bree.run('will-send-msg');
|
|
|
|
|
|
|
|
jobManager.bree.workers['will-send-msg'].postMessage('hello from Ghost!');
|
|
|
|
|
|
|
|
// Give time for worker (worker thread) <-> parent process (job manager) communication
|
|
|
|
await delay(1000);
|
|
|
|
|
|
|
|
should(workerMessageHandlerSpy.called).be.true();
|
|
|
|
should(workerMessageHandlerSpy.args[0][0].name).equal('will-send-msg');
|
2021-03-03 02:26:37 +03:00
|
|
|
should(workerMessageHandlerSpy.args[0][0].message).equal('Worker received: hello from Ghost!');
|
2021-02-22 09:10:47 +03:00
|
|
|
});
|
2020-12-07 06:50:41 +03:00
|
|
|
});
|
2020-11-05 06:39:51 +03:00
|
|
|
});
|
2020-11-17 08:14:37 +03:00
|
|
|
|
2022-07-21 21:39:54 +03:00
|
|
|
describe('Add one off job', function () {
|
2022-07-26 17:12:44 +03:00
|
|
|
it('throws if name parameter is not provided', async function () {
|
|
|
|
const jobManager = new JobManager({});
|
|
|
|
|
|
|
|
try {
|
|
|
|
await jobManager.addOneOffJob({
|
|
|
|
job: () => {}
|
|
|
|
});
|
|
|
|
throw new Error('should have thrown');
|
|
|
|
} catch (err) {
|
|
|
|
should.equal(err.message, 'The name parameter is required for a one off job.');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
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()
|
|
|
|
};
|
2022-07-21 21:39:54 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
const jobManager = new JobManager({JobModel});
|
2022-07-21 21:39:54 +03:00
|
|
|
await jobManager.addOneOffJob({
|
|
|
|
job: spy,
|
2022-07-26 17:18:48 +03:00
|
|
|
name: 'unique name',
|
2022-07-21 21:39:54 +03:00
|
|
|
data: 'test data'
|
|
|
|
});
|
2022-07-22 18:43:08 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
assert.equal(JobModel.add.called, true);
|
2022-07-22 18:43:08 +03:00
|
|
|
});
|
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
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')
|
|
|
|
};
|
2022-07-22 18:43:08 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
const jobManager = new JobManager({JobModel});
|
2022-07-22 18:43:08 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
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.');
|
|
|
|
}
|
|
|
|
});
|
2022-07-22 18:43:08 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
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'})
|
|
|
|
};
|
2022-07-22 18:43:08 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
const jobManager = new JobManager({JobModel});
|
|
|
|
|
|
|
|
jobManager.addOneOffJob({
|
|
|
|
job: path.resolve(__dirname, './jobs/message.js'),
|
|
|
|
name: 'successful-oneoff'
|
|
|
|
});
|
|
|
|
|
|
|
|
// allow job to get picked up and executed
|
|
|
|
await delay(100);
|
2022-07-22 18:43:08 +03:00
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
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');
|
2022-07-22 18:43:08 +03:00
|
|
|
});
|
|
|
|
|
2022-07-26 17:18:48 +03:00
|
|
|
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');
|
|
|
|
});
|
2022-07-22 18:43:08 +03:00
|
|
|
});
|
2022-07-21 21:39:54 +03:00
|
|
|
});
|
|
|
|
|
2021-01-06 03:46:47 +03:00
|
|
|
describe('Remove a job', function () {
|
2020-12-08 06:43:18 +03:00
|
|
|
it('removes a scheduled job from the queue', async function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2020-12-08 06:43:18 +03:00
|
|
|
|
|
|
|
const timeInTenSeconds = new Date(Date.now() + 10);
|
|
|
|
const jobPath = path.resolve(__dirname, './jobs/simple.js');
|
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:45:23 +03:00
|
|
|
at: timeInTenSeconds,
|
|
|
|
job: jobPath,
|
|
|
|
name: 'job-in-ten'
|
|
|
|
});
|
2020-12-08 06:43:18 +03:00
|
|
|
jobManager.bree.config.jobs[0].name.should.equal('job-in-ten');
|
|
|
|
|
|
|
|
await jobManager.removeJob('job-in-ten');
|
|
|
|
|
|
|
|
should(jobManager.bree.config.jobs[0]).be.undefined;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-11-17 08:14:37 +03:00
|
|
|
describe('Shutdown', function () {
|
2021-01-06 03:45:23 +03:00
|
|
|
it('gracefully shuts down an inline jobs', async function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2020-11-17 08:14:37 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:45:23 +03:00
|
|
|
job: require('./jobs/timed-job'),
|
|
|
|
data: 200,
|
|
|
|
offloaded: false
|
|
|
|
});
|
2020-11-17 08:14:37 +03:00
|
|
|
|
|
|
|
should(jobManager.queue.idle()).be.false();
|
|
|
|
|
|
|
|
await jobManager.shutdown();
|
|
|
|
|
|
|
|
should(jobManager.queue.idle()).be.true();
|
|
|
|
});
|
2020-11-19 07:58:41 +03:00
|
|
|
|
|
|
|
it('gracefully shuts down an interval job', async function () {
|
2021-12-02 15:48:48 +03:00
|
|
|
const jobManager = new JobManager({});
|
2020-11-19 07:58:41 +03:00
|
|
|
|
2022-07-21 20:56:17 +03:00
|
|
|
jobManager.addJob({
|
2021-01-06 03:45:23 +03:00
|
|
|
at: 'every 5 seconds',
|
|
|
|
job: path.resolve(__dirname, './jobs/graceful.js')
|
|
|
|
});
|
2020-11-19 07:58:41 +03:00
|
|
|
|
|
|
|
await delay(1); // let the job execution kick in
|
|
|
|
|
2020-11-23 04:24:24 +03:00
|
|
|
should(Object.keys(jobManager.bree.workers).length).equal(0);
|
|
|
|
should(Object.keys(jobManager.bree.timeouts).length).equal(0);
|
|
|
|
should(Object.keys(jobManager.bree.intervals).length).equal(1);
|
2020-11-19 07:58:41 +03:00
|
|
|
|
|
|
|
await jobManager.shutdown();
|
|
|
|
|
2020-11-23 04:24:24 +03:00
|
|
|
should(Object.keys(jobManager.bree.intervals).length).equal(0);
|
2020-11-19 07:58:41 +03:00
|
|
|
});
|
2020-11-17 08:14:37 +03:00
|
|
|
});
|
2020-11-05 06:39:51 +03:00
|
|
|
});
|