toad-scheduler
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -5,3 +5,3 @@ import { AsyncTask } from '../../common/AsyncTask'; | ||
import { SimpleIntervalSchedule } from './SimpleIntervalSchedule'; | ||
export declare type JobOptions = { | ||
export type JobOptions = { | ||
preventOverrun?: boolean; | ||
@@ -8,0 +8,0 @@ id?: string; |
@@ -1,2 +0,2 @@ | ||
export declare type SimpleIntervalSchedule = { | ||
export type SimpleIntervalSchedule = { | ||
days?: number; | ||
@@ -3,0 +3,0 @@ hours?: number; |
@@ -13,2 +13,3 @@ import { SimpleIntervalJob } from './engines/simple-interval/SimpleIntervalJob'; | ||
getById(id: string): Job; | ||
existsById(id: string): boolean; | ||
removeById(id: string): Job | undefined; | ||
@@ -15,0 +16,0 @@ stopById(id: string): void; |
@@ -40,2 +40,9 @@ "use strict"; | ||
} | ||
existsById(id) { | ||
const job = this.jobRegistry[id]; | ||
if (!job) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
removeById(id) { | ||
@@ -42,0 +49,0 @@ const job = this.jobRegistry[id]; |
{ | ||
"name": "toad-scheduler", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"license": "MIT", | ||
@@ -25,9 +25,9 @@ "description": "In-memory Node.js and browser job scheduler", | ||
"@types/jest": "^28.1.8", | ||
"@types/node": "^18.8.4", | ||
"@typescript-eslint/eslint-plugin": "^5.40.0", | ||
"@typescript-eslint/parser": "^5.40.0", | ||
"@types/node": "^18.11.11", | ||
"@typescript-eslint/eslint-plugin": "^5.45.1", | ||
"@typescript-eslint/parser": "^5.45.1", | ||
"eslint": "^8.25.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"jasmine-core": "^4.4.0", | ||
"jasmine-core": "^4.5.0", | ||
"jest": "^28.1.3", | ||
@@ -38,5 +38,5 @@ "karma": "^6.4.1", | ||
"karma-typescript": "^5.5.3", | ||
"prettier": "^2.7.1", | ||
"prettier": "^2.8.0", | ||
"ts-jest": "^28.0.8", | ||
"typescript": "4.8.4" | ||
"typescript": "4.9.3" | ||
}, | ||
@@ -43,0 +43,0 @@ "homepage": "https://github.com/kibertoad/toad-scheduler", |
@@ -134,2 +134,86 @@ # toad-scheduler | ||
## Usage in clustered environments | ||
`toad-scheduler` does not persist its state by design, and has no out-of-the-box concurrency management features. In case it is necessary | ||
to prevent parallel execution of jobs in clustered environment, it is highly recommended to use [redis-semaphore](https://github.com/swarthy/redis-semaphore) in your tasks. | ||
Here is an example: | ||
```ts | ||
import { randomUUID } from 'crypto' | ||
import type Redis from 'ioredis' | ||
import { Mutex } from 'redis-semaphore' | ||
import type { LockOptions } from 'redis-semaphore' | ||
import { AsyncTask } from 'toad-scheduler'; | ||
export type BackgroundJobConfiguration = { | ||
jobId: string | ||
} | ||
export type LockConfiguration = { | ||
lockName?: string | ||
refreshInterval?: number | ||
lockTimeout: number | ||
} | ||
export abstract class AbstractBackgroundJob { | ||
public readonly jobId: string | ||
protected readonly redis: Redis | ||
protected constructor( | ||
options: BackgroundJobConfiguration, | ||
redis: Redis, | ||
) { | ||
this.jobId = options.jobId | ||
this.redis = redis | ||
} | ||
protected abstract processInternal(executionUuid: string): Promise<void> | ||
async process() { | ||
const uuid = randomUUID() | ||
try { | ||
await this.processInternal(uuid) | ||
} catch (err) { | ||
console.error(logObject) | ||
} | ||
} | ||
protected getJobMutex(key: string, options: LockOptions) { | ||
return new Mutex(this.redis, this.getJobLockName(key), options) | ||
} | ||
protected async tryAcquireExclusiveLock(lockConfiguration: LockConfiguration) { | ||
const mutex = this.getJobMutex(lockConfiguration.lockName ?? 'exclusive', { | ||
acquireAttemptsLimit: 1, | ||
refreshInterval: lockConfiguration.refreshInterval, | ||
lockTimeout: lockConfiguration.lockTimeout, | ||
}) | ||
const lock = await mutex.tryAcquire() | ||
// If someone else already has this lock, skip | ||
if (!lock) { | ||
return | ||
} | ||
return mutex | ||
} | ||
protected getJobLockName(key: string) { | ||
return `${this.jobId}:locks:${key}` | ||
} | ||
} | ||
function createTask(job: AbstractBackgroundJob): AsyncTask { | ||
return new AsyncTask( | ||
job.jobId, | ||
() => { | ||
return job.process() | ||
}, | ||
) | ||
} | ||
``` | ||
## API for schedule | ||
@@ -157,2 +241,3 @@ | ||
* `getById(id: string): Job` - returns the job with a given id. | ||
* `existsById(id: string): boolean` - returns true if job with given id exists, false otherwise. | ||
* `stopById(id: string): void` - stops the job with a given id. | ||
@@ -159,0 +244,0 @@ * `removeById(id: string): Job | undefined` - stops the job with a given id and removes it from the scheduler. If no such job exists, returns `undefined`, otherwise returns the job. |
Sorry, the diff of this file is not supported yet
39832
474
249