test('can provide an error if connection failed', async () => { let connectionDetails = { pkg: specHelper.connectionDetails.pkg, host: 'wronghostname', password: specHelper.connectionDetails.password, port: specHelper.connectionDetails.port, database: specHelper.connectionDetails.database, namespace: specHelper.connectionDetails.namespace } scheduler = new NodeResque.Scheduler({ connection: connectionDetails, timeout: specHelper.timeout }) scheduler.on('poll', () => { throw new Error('Should not emit poll') }) scheduler.on('master', () => { throw new Error('Should not emit master') }) await new Promise(async (resolve) => { scheduler.connect() scheduler.on('error', async (error) => { expect(error.message).toMatch(/getaddrinfo ENOTFOUND/) await scheduler.end() resolve() }) }) })
await new Promise(async (resolve) => { scheduler.connect() scheduler.on('error', async (error) => { expect(error.message).toMatch(/getaddrinfo ENOTFOUND/) await scheduler.end() resolve() }) })
beforeAll(async () => { await specHelper.connect() await specHelper.cleanup() queue = new NodeResque.Queue({connection: specHelper.cleanConnectionDetails(), queue: specHelper.queue}, jobs) scheduler = new NodeResque.Scheduler({connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout}) await scheduler.connect() scheduler.start() await queue.connect() })
beforeEach(async () => { await specHelper.cleanup() scheduler = new NodeResque.Scheduler({ connection: specHelper.connectionDetails, timeout: specHelper.timeout, stuckWorkerTimeout: 1000 }) queue = new NodeResque.Queue({connection: specHelper.connectionDetails, queue: specHelper.queue}) await scheduler.connect() await queue.connect() })
test('SSTF#run - batch with pagefaults - final context', assert => { let scheduler = new Scheduler(SSTF, examples.simulation15()); let expected = LotParser( '*147 133 130 110 *150 *149 175 186 201 202 212 257 270 ' + '285 288 99 94 85 81 75 59 50 42 25' ); let results = scheduler.run(); for (let step of results) { assert.true(step.requirement.equals(expected.first())); } assert.equals(scheduler.context.direction, false); assert.equals(scheduler.context.movements, 487); assert.end(); })
test('SSTF#run - single lot - final context', assert => { let scheduler = new Scheduler( SSTF, examples.simulation12()); let expected = LotParser('86 91 94 102 115 120 130 147 150 175 177 66 58 32'); let results = scheduler.run(); for (let step of results) { assert.true(step.requirement.equals(expected.first())); } assert.equals(scheduler.context.direction, false); assert.equals(scheduler.context.movements, 239); assert.end(); });
test('SSTF#run - lots batch - final context', assert => { let scheduler = new Scheduler(SSTF, examples.simulation14()); let expected = LotParser( '140 147 150 126 118 115 99 94 81 75 55 ' + '50 22 175 212 220 225 266 277 280' ); let results = scheduler.run(); for (let step of results) { assert.true(step.requirement.equals(expected.first())); } assert.equals(scheduler.context.movements, 399); assert.true(scheduler.context.direction); assert.end(); })
test('should only have one master, and can failover', async () => { const shedulerOne = new NodeResque.Scheduler({connection: specHelper.connectionDetails, name: 'scheduler_1', timeout: specHelper.timeout}) const shedulerTwo = new NodeResque.Scheduler({connection: specHelper.connectionDetails, name: 'scheduler_2', timeout: specHelper.timeout}) await shedulerOne.connect() await shedulerTwo.connect() await shedulerOne.start() await shedulerTwo.start() await new Promise((resolve) => { setTimeout(resolve, specHelper.timeout * 2) }) expect(shedulerOne.master).toBe(true) expect(shedulerTwo.master).toBe(false) await shedulerOne.end() await new Promise((resolve) => { setTimeout(resolve, specHelper.timeout * 2) }) expect(shedulerOne.master).toBe(false) expect(shedulerTwo.master).toBe(true) await shedulerTwo.end() })
test('can connect', async () => { scheduler = new NodeResque.Scheduler({connection: specHelper.connectionDetails, timeout: specHelper.timeout}) await scheduler.connect() await scheduler.end() })
scheduler.on('error', async (error) => { expect(error.message).toMatch(/getaddrinfo ENOTFOUND/) await scheduler.end() resolve() })
async function boot () { // //////////////////////// // SET UP THE CONNECTION // // //////////////////////// const connectionDetails = { pkg: 'ioredis', host: '127.0.0.1', password: null, port: 6379, database: 0 // namespace: 'resque', // looping: true, // options: {password: '******'}, } // /////////////////////////// // DEFINE YOUR WORKER TASKS // // /////////////////////////// const jobs = { 'stuck': { perform: async function () { console.log(`${this.name} is starting stuck job...`) await new Promise((resolve) => { clearTimeout(this.pingTimer)// stop the worker from checkin in, like the process crashed setTimeout(resolve, 60 * 60 * 1000) // 1 hour job }) } } } // ///////////////// // START A WORKER // // ///////////////// const worker = new NodeResque.Worker({connection: connectionDetails, queues: ['stuckJobs']}, jobs) await worker.connect() worker.start() // //////////////////// // START A SCHEDULER // // //////////////////// const scheduler = new NodeResque.Scheduler({ stuckWorkerTimeout: (10 * 1000), connection: connectionDetails }) await scheduler.connect() scheduler.start() // ////////////////////// // REGESTER FOR EVENTS // // ////////////////////// worker.on('start', () => { console.log('worker started') }) worker.on('end', () => { console.log('worker ended') }) worker.on('cleaning_worker', (worker, pid) => { console.log(`cleaning old worker ${worker}`) }) worker.on('poll', (queue) => { console.log(`worker polling ${queue}`) }) worker.on('ping', (time) => { console.log(`worker check in @ ${time}`) }) worker.on('job', (queue, job) => { console.log(`working job ${queue} ${JSON.stringify(job)}`) }) worker.on('reEnqueue', (queue, job, plugin) => { console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`) }) worker.on('success', (queue, job, result) => { console.log(`job success ${queue} ${JSON.stringify(job)} >> ${result}`) }) worker.on('failure', (queue, job, failure) => { console.log(`job failure ${queue} ${JSON.stringify(job)} >> ${failure}`) }) worker.on('error', (error, queue, job) => { console.log(`error ${queue} ${JSON.stringify(job)} >> ${error}`) }) worker.on('pause', () => { console.log('worker paused') }) scheduler.on('start', () => { console.log('scheduler started') }) scheduler.on('end', () => { console.log('scheduler ended') }) scheduler.on('poll', () => { console.log('scheduler polling') }) scheduler.on('master', (state) => { console.log('scheduler became master') }) scheduler.on('error', (error) => { console.log(`scheduler error >> ${error}`) }) scheduler.on('workingTimestamp', (timestamp) => { console.log(`scheduler working timestamp ${timestamp}`) }) scheduler.on('transferredJob', (timestamp, job) => { console.log(`scheduler enquing job ${timestamp} >> ${JSON.stringify(job)}`) }) scheduler.on('cleanStuckWorker', (workerName, errorPayload, delta) => { console.log(`failing ${workerName} (stuck for ${delta}s) and failing job: ${JSON.stringify(errorPayload)}`) process.exit() }) // ////////////////////// // CONNECT TO A QUEUE // // ////////////////////// const queue = new NodeResque.Queue({connection: connectionDetails}, jobs) queue.on('error', function (error) { console.log(error) }) await queue.connect() await queue.enqueue('stuckJobs', 'stuck', ['oh no']) }