diff --git a/.eslintrc.json b/.eslintrc.json index 4da298f..bb23f54 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,12 +1,10 @@ { "extends": [ "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended" + "plugin:@typescript-eslint/recommended" ], "plugins": [ - "@typescript-eslint", - "prettier" + "@typescript-eslint" ], "parser": "@typescript-eslint/parser", "parserOptions": { @@ -18,12 +16,6 @@ "node": true }, "rules": { - "prettier/prettier": [ - "error", - { - "endOfLine": "auto" - } - ], "@typescript-eslint/ban-ts-ignore": "off", "@typescript-eslint/no-use-before-define": "off", "@typescript-eslint/no-non-null-assertion": "off", diff --git a/lib/common/AsyncTask.ts b/lib/common/AsyncTask.ts index 82476f5..325ce07 100644 --- a/lib/common/AsyncTask.ts +++ b/lib/common/AsyncTask.ts @@ -10,7 +10,7 @@ export class AsyncTask { constructor( id: string, handler: (taskId?: string, jobId?: string) => Promise, - errorHandler?: (err: Error) => void + errorHandler?: (err: Error) => void, ) { this.id = id this.handler = handler diff --git a/lib/common/Task.ts b/lib/common/Task.ts index f82a44f..98ce0e7 100644 --- a/lib/common/Task.ts +++ b/lib/common/Task.ts @@ -10,7 +10,7 @@ export class Task { constructor( id: string, handler: (taskId?: string, jobId?: string) => void, - errorHandler?: (err: Error) => void + errorHandler?: (err: Error) => void, ) { this.id = id this.handler = handler diff --git a/lib/engines/cron/CronJob.ts b/lib/engines/cron/CronJob.ts index 8f951ca..ec8a1e6 100644 --- a/lib/engines/cron/CronJob.ts +++ b/lib/engines/cron/CronJob.ts @@ -2,6 +2,7 @@ import { Job, JobStatus } from '../../common/Job' import { Task } from '../../common/Task' import { AsyncTask } from '../../common/AsyncTask' import { JobOptions } from '../simple-interval/SimpleIntervalJob' +import { Cron } from 'croner' export const CRON_EVERY_SECOND = '* * * * * *' @@ -18,11 +19,6 @@ export type CronSchedule = { timezone?: string } -export type Cron = { - isRunning(): boolean - stop(): void -} - export class CronJob extends Job { private readonly schedule: CronSchedule private readonly task: Task | AsyncTask @@ -32,7 +28,7 @@ export class CronJob extends Job { constructor(schedule: CronSchedule, task: Task | AsyncTask, options: JobOptions = {}) { super(options.id) - this.preventOverrun = false + this.preventOverrun = options.preventOverrun || false this.schedule = schedule this.task = task } @@ -43,27 +39,17 @@ export class CronJob extends Job { } start(): void { - // lazy-require croner to avoid mandatory dependency - let croner - try { - croner = require('croner') - } catch (err) { - /* istanbul ignore next */ - throw new Error( - 'Please install "croner" (run "npm i croner") in case you want to use Cron jobs.' - ) - } - - this.cronInstance = croner.Cron( + this.cronInstance = Cron( this.schedule.cronExpression, { timezone: this.schedule.timezone, + protect: false, }, () => { if (!this.task.isExecuting || !this.preventOverrun) { this.task.execute(this.id) } - } + }, ) } diff --git a/lib/engines/simple-interval/LongIntervalJob.ts b/lib/engines/simple-interval/LongIntervalJob.ts index 3381356..119ddb7 100644 --- a/lib/engines/simple-interval/LongIntervalJob.ts +++ b/lib/engines/simple-interval/LongIntervalJob.ts @@ -42,7 +42,7 @@ export class LongIntervalJob extends Job { { milliseconds: Math.min(MAX_TIMEOUT_DURATION_MS - 1, remainingMs), }, - timeEater + timeEater, ) this.childJob.start() } else { @@ -55,7 +55,7 @@ export class LongIntervalJob extends Job { new Task('Final mile task', () => { this.setTimeEatingJob(toMsecs(this.schedule)) return this.task.execute(this.id) - }) + }), ) this.childJob.start() } @@ -66,7 +66,7 @@ export class LongIntervalJob extends Job { { milliseconds: Math.min(MAX_TIMEOUT_DURATION_MS - 1, startingRemainingMs), }, - timeEater + timeEater, ) this.childJob.start() } diff --git a/lib/engines/simple-interval/SimpleIntervalJob.ts b/lib/engines/simple-interval/SimpleIntervalJob.ts index b14169a..235da05 100644 --- a/lib/engines/simple-interval/SimpleIntervalJob.ts +++ b/lib/engines/simple-interval/SimpleIntervalJob.ts @@ -27,7 +27,7 @@ export class SimpleIntervalJob extends Job { // See https://github.com/kibertoad/toad-scheduler/issues/24 if (time >= 2147483647) { throw new Error( - 'Due to setInterval limitations, no intervals longer than 24.85 days can be scheduled correctly. Please create LongIntervalJob instead.' + 'Due to setInterval limitations, no intervals longer than 24.85 days can be scheduled correctly. Please create LongIntervalJob instead.', ) } diff --git a/package.json b/package.json index a986484..b7c2ae0 100644 --- a/package.json +++ b/package.json @@ -21,24 +21,24 @@ "format": "prettier --write \"{lib,test}/**/*.{js,ts}\" index.ts", "prepublishOnly": "npm run build" }, + "dependencies": { + "croner": "^7.0.5" + }, "devDependencies": { - "@types/jest": "^29.5.2", + "@types/jest": "^29.5.12", "@types/node": "^20.3.1", - "@typescript-eslint/eslint-plugin": "^5.59.11", - "@typescript-eslint/parser": "^5.59.11", - "croner": "^7.0.1", - "eslint": "^8.42.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.0", - "jasmine-core": "^5.0.1", - "jest": "^29.5.0", + "@typescript-eslint/eslint-plugin": "^6.20.0", + "@typescript-eslint/parser": "^6.20.0", + "eslint": "^8.56.0", + "jasmine-core": "^5.1.1", + "jest": "^29.7.0", "karma": "^6.4.2", "karma-chrome-launcher": "^3.2.0", "karma-jasmine": "^5.1.0", "karma-typescript": "^5.5.4", "prettier": "^3.0.0", - "ts-jest": "^29.1.0", - "typescript": "^5.1.3" + "ts-jest": "^29.1.2", + "typescript": "5.2.2" }, "homepage": "https://github.com/kibertoad/toad-scheduler", "repository": { diff --git a/test/AsyncTask.spec.ts b/test/AsyncTask.spec.ts index e94ca43..aa4a2ca 100644 --- a/test/AsyncTask.spec.ts +++ b/test/AsyncTask.spec.ts @@ -27,14 +27,14 @@ describe('ToadScheduler', () => { }, (err: Error) => { error = err.message - } + }, ) const job = new SimpleIntervalJob( { seconds: 1, runImmediately: true, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -68,14 +68,14 @@ describe('ToadScheduler', () => { }, (err: Error) => { error = err.message - } + }, ) const job = new SimpleIntervalJob( { seconds: 1, runImmediately: true, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -107,14 +107,14 @@ describe('ToadScheduler', () => { error = err.message throw new Error('error while handling error') }) - } + }, ) const job = new SimpleIntervalJob( { seconds: 1, runImmediately: true, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -139,13 +139,13 @@ describe('ToadScheduler', () => { }, (err: Error) => { error = err.message - } + }, ) const job = new SimpleIntervalJob( { milliseconds: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -169,13 +169,13 @@ describe('ToadScheduler', () => { return Promise.reject(new Error('kaboom2')) }) }, - () => {} + () => {}, ) const job = new SimpleIntervalJob( { milliseconds: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -198,7 +198,7 @@ describe('ToadScheduler', () => { Promise.resolve() return Promise.reject(new Error('kaboom2')) }, - () => {} + () => {}, ) const job = new SimpleIntervalJob( { @@ -207,7 +207,7 @@ describe('ToadScheduler', () => { task, { id: 'jobId', - } + }, ) scheduler.addSimpleIntervalJob(job) diff --git a/test/CronJob.spec.ts b/test/CronJob.spec.ts index 4db92e0..46d209f 100644 --- a/test/CronJob.spec.ts +++ b/test/CronJob.spec.ts @@ -5,6 +5,12 @@ import { advanceTimersByTime, mockTimers, setSystemTime, unMockTimers } from './ import { AsyncTask } from '../lib/common/AsyncTask' import { CRON_EVERY_MINUTE, CRON_EVERY_SECOND, CronJob } from '../lib/engines/cron/CronJob' +function wait(ms: number) { + return new Promise((resolve) => { + setTimeout(resolve, ms) + }) +} + function resetTime() { setSystemTime({ hours: 1, minutes: 0, seconds: 0 }) } @@ -27,7 +33,7 @@ describe('ToadScheduler', () => { { cronExpression: CRON_EVERY_SECOND, }, - task + task, ) scheduler.addCronJob(job) expect(job.getStatus()).toBe('running') @@ -40,7 +46,7 @@ describe('ToadScheduler', () => { { cronExpression: CRON_EVERY_MINUTE, }, - task + task, ) scheduler.addCronJob(job) scheduler.stop() @@ -57,7 +63,7 @@ describe('ToadScheduler', () => { { cronExpression: '*/20 * * * * *', }, - task + task, ) scheduler.addCronJob(job) @@ -76,45 +82,41 @@ describe('ToadScheduler', () => { }) it('allows preventing CronJob execution overrun for async tasks', async () => { + unMockTimers() + let counter = 0 const scheduler = new ToadScheduler() - const task = new AsyncTask('simple task', () => { + const task = new AsyncTask('simple task', async () => { counter++ - advanceTimersByTime(6000) - return Promise.resolve(undefined) + await wait(2000) }) + const job = new CronJob( { - cronExpression: '*/2 * * * * *', + cronExpression: '*/1 * * * * *', }, task, { preventOverrun: true, - } + }, ) scheduler.addCronJob(job) expect(counter).toBe(0) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) + await Promise.resolve() + await wait(1400) + await Promise.resolve() + expect(counter).toBe(1) + await Promise.resolve() + await wait(2800) + await Promise.resolve() expect(counter).toBe(2) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - expect(counter).toBe(5) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - advanceTimersByTime(1000) - expect(counter).toBe(7) + await Promise.resolve() + await wait(2800) + await Promise.resolve() + expect(counter).toBe(3) scheduler.stop() - }) + }, 20000) it('allows enabling CronJob execution overrun', async () => { let counter = 0 @@ -131,7 +133,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: false, - } + }, ) scheduler.addCronJob(job) @@ -173,7 +175,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: true, - } + }, ) scheduler.addCronJob(job) @@ -225,7 +227,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: true, - } + }, ) scheduler.addCronJob(job) @@ -264,7 +266,7 @@ describe('ToadScheduler', () => { { cronExpression: '*/20 * * * * *', }, - task + task, ) scheduler.addCronJob(job) scheduler.addCronJob(job) @@ -293,7 +295,7 @@ describe('ToadScheduler', () => { { cronExpression: '*/20 * * * * *', }, - task + task, ) scheduler.addCronJob(job) diff --git a/test/LongIntervalJob.spec.ts b/test/LongIntervalJob.spec.ts index 1f50946..bf2dfc3 100644 --- a/test/LongIntervalJob.spec.ts +++ b/test/LongIntervalJob.spec.ts @@ -24,7 +24,7 @@ describe('ToadScheduler', () => { { seconds: 20, }, - task + task, ) scheduler.addLongIntervalJob(job) expect(job.getStatus()).toBe('running') @@ -37,7 +37,7 @@ describe('ToadScheduler', () => { { seconds: 20, }, - task + task, ) scheduler.addLongIntervalJob(job) scheduler.stop() @@ -54,7 +54,7 @@ describe('ToadScheduler', () => { { seconds: 20, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -86,7 +86,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: true, - } + }, ) scheduler.addLongIntervalJob(job) @@ -114,7 +114,7 @@ describe('ToadScheduler', () => { hours: 33, runImmediately: true, }, - task + task, ) expect(counter).toBe(0) @@ -133,7 +133,7 @@ describe('ToadScheduler', () => { { milliseconds: 33, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -157,7 +157,7 @@ describe('ToadScheduler', () => { { milliseconds: 10, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -180,7 +180,7 @@ describe('ToadScheduler', () => { { milliseconds: 10, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -206,7 +206,7 @@ describe('ToadScheduler', () => { { minutes: 5, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -230,7 +230,7 @@ describe('ToadScheduler', () => { { hours: 1, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -254,7 +254,7 @@ describe('ToadScheduler', () => { { days: 1, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -283,7 +283,7 @@ describe('ToadScheduler', () => { { days: 25, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -308,7 +308,7 @@ describe('ToadScheduler', () => { { days: 25, }, - task + task, ) scheduler.addLongIntervalJob(job) expect(job.getStatus()).toEqual('running') @@ -332,7 +332,7 @@ describe('ToadScheduler', () => { { days: 25, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -369,7 +369,7 @@ describe('ToadScheduler', () => { { days: 55, }, - task + task, ) scheduler.addLongIntervalJob(job) @@ -401,7 +401,7 @@ describe('ToadScheduler', () => { seconds: 4, milliseconds: 5, }, - task + task, ) scheduler.addLongIntervalJob(job) diff --git a/test/SimpleIntervalJob.spec.ts b/test/SimpleIntervalJob.spec.ts index 2fa5fb8..c520b44 100644 --- a/test/SimpleIntervalJob.spec.ts +++ b/test/SimpleIntervalJob.spec.ts @@ -22,7 +22,7 @@ describe('ToadScheduler', () => { { seconds: 20, }, - task + task, ) scheduler.addSimpleIntervalJob(job) expect(job.getStatus()).toBe('running') @@ -35,7 +35,7 @@ describe('ToadScheduler', () => { { seconds: 20, }, - task + task, ) scheduler.addSimpleIntervalJob(job) scheduler.stop() @@ -52,7 +52,7 @@ describe('ToadScheduler', () => { { seconds: 20, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -84,7 +84,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: true, - } + }, ) scheduler.addSimpleIntervalJob(job) @@ -116,7 +116,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: true, - } + }, ) scheduler.addSimpleIntervalJob(job) @@ -168,7 +168,7 @@ describe('ToadScheduler', () => { task, { preventOverrun: true, - } + }, ) scheduler.addSimpleIntervalJob(job) @@ -208,7 +208,7 @@ describe('ToadScheduler', () => { hours: 33, runImmediately: true, }, - task + task, ) expect(counter).toBe(0) @@ -227,7 +227,7 @@ describe('ToadScheduler', () => { { milliseconds: 33, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -251,7 +251,7 @@ describe('ToadScheduler', () => { { milliseconds: 10, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -274,7 +274,7 @@ describe('ToadScheduler', () => { { milliseconds: 10, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -300,7 +300,7 @@ describe('ToadScheduler', () => { { minutes: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -324,7 +324,7 @@ describe('ToadScheduler', () => { { hours: 1, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -348,7 +348,7 @@ describe('ToadScheduler', () => { { days: 1, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -372,7 +372,7 @@ describe('ToadScheduler', () => { { days: 25, }, - task + task, ) expect(() => scheduler.addSimpleIntervalJob(job)).toThrowError(/can be scheduled correctly/) @@ -394,7 +394,7 @@ describe('ToadScheduler', () => { seconds: 4, milliseconds: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) diff --git a/test/Task.spec.ts b/test/Task.spec.ts index 58ee9c3..3af34af 100644 --- a/test/Task.spec.ts +++ b/test/Task.spec.ts @@ -22,14 +22,14 @@ describe('ToadScheduler', () => { }, (err: Error) => { error = err.message - } + }, ) const job = new SimpleIntervalJob( { seconds: 1, runImmediately: true, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -60,14 +60,14 @@ describe('ToadScheduler', () => { error = err.message throw new Error('Error while handling an error') }) - } + }, ) const job = new SimpleIntervalJob( { seconds: 1, runImmediately: true, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -97,14 +97,14 @@ describe('ToadScheduler', () => { .then(() => { throw new Error('Error while handling an error') }) - } + }, ) const job = new SimpleIntervalJob( { seconds: 1, runImmediately: true, }, - task + task, ) scheduler.addSimpleIntervalJob(job) diff --git a/test/toadScheduler-unhandled.spec.ts b/test/toadScheduler-unhandled.spec.ts index b1c9795..6797e34 100644 --- a/test/toadScheduler-unhandled.spec.ts +++ b/test/toadScheduler-unhandled.spec.ts @@ -36,7 +36,7 @@ describe('Rejection handling', () => { { milliseconds: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -66,7 +66,7 @@ describe('Rejection handling', () => { { milliseconds: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) @@ -94,7 +94,7 @@ describe('Rejection handling', () => { { milliseconds: 5, }, - task + task, ) scheduler.addSimpleIntervalJob(job) diff --git a/test/toadScheduler.spec.ts b/test/toadScheduler.spec.ts index 74f2e7c..e87e36d 100644 --- a/test/toadScheduler.spec.ts +++ b/test/toadScheduler.spec.ts @@ -24,7 +24,7 @@ describe('ToadScheduler', () => { seconds: 20, }, task, - { id: 'id' } + { id: 'id' }, ) scheduler.addSimpleIntervalJob(job) const retrievedJob = scheduler.getById('id') @@ -42,7 +42,7 @@ describe('ToadScheduler', () => { seconds: 20, }, task, - { id: 'id' } + { id: 'id' }, ) scheduler.addSimpleIntervalJob(job) const result = scheduler.existsById('id') @@ -57,7 +57,7 @@ describe('ToadScheduler', () => { seconds: 20, }, task, - { id: 'id' } + { id: 'id' }, ) scheduler.addSimpleIntervalJob(job) const result = scheduler.existsById('id2') @@ -81,14 +81,14 @@ describe('ToadScheduler', () => { milliseconds: 1, }, task, - { id: 'job1' } + { id: 'job1' }, ) const job2 = new SimpleIntervalJob( { milliseconds: 10, }, task2, - { id: 'job2' } + { id: 'job2' }, ) scheduler.addSimpleIntervalJob(job) @@ -139,14 +139,14 @@ describe('ToadScheduler', () => { milliseconds: 1, }, task, - { id: 'job1' } + { id: 'job1' }, ) const job2 = new SimpleIntervalJob( { milliseconds: 10, }, task2, - { id: 'job2' } + { id: 'job2' }, ) scheduler.addSimpleIntervalJob(job) @@ -191,14 +191,14 @@ describe('ToadScheduler', () => { milliseconds: 1, }, task, - { id: 'job1' } + { id: 'job1' }, ) const job2 = new SimpleIntervalJob( { milliseconds: 10, }, task2, - { id: 'job2' } + { id: 'job2' }, ) scheduler.addSimpleIntervalJob(job) @@ -230,14 +230,14 @@ describe('ToadScheduler', () => { seconds: 20, }, task, - { id: 'id' } + { id: 'id' }, ) const job2 = new SimpleIntervalJob( { seconds: 20, }, task, - { id: 'id2' } + { id: 'id2' }, ) scheduler.addSimpleIntervalJob(job) scheduler.addSimpleIntervalJob(job2) @@ -264,14 +264,14 @@ describe('ToadScheduler', () => { seconds: 20, }, task, - { id: 'id' } + { id: 'id' }, ) const job2 = new SimpleIntervalJob( { seconds: 20, }, task, - { id: 'id2' } + { id: 'id2' }, ) scheduler.addSimpleIntervalJob(job) scheduler.addSimpleIntervalJob(job2) @@ -294,14 +294,14 @@ describe('ToadScheduler', () => { milliseconds: 1, }, new NoopTask(), - { id: 'job1' } + { id: 'job1' }, ) const job2 = new SimpleIntervalJob( { milliseconds: 10, }, new NoopTask(), - { id: 'job1' } + { id: 'job1' }, ) scheduler.addSimpleIntervalJob(job) @@ -336,13 +336,13 @@ describe('ToadScheduler', () => { { milliseconds: 1, }, - task + task, ) const job2 = new SimpleIntervalJob( { milliseconds: 10, }, - task2 + task2, ) scheduler.addSimpleIntervalJob(job)