Josk
Node.js setInterval and CRON tasks scheduler and manager for horizontally scaled multi-server applications
Install / Use
/learn @veliovgroup/JoskREADME
<a href="https://ostr.io/info/built-by-developers-for-developers?ref=github-josk-repo-top"><img src="https://ostr.io/apple-touch-icon-60x60.png" height="20"></a>
<a href="https://meteor-files.com/?ref=github-josk-repo-top"><img src="https://meteor-files.com/apple-touch-icon-60x60.png" height="20"></a>
JoSk
"JoSk" is a Node.js task manager for horizontally scaled apps and apps that would need to scale horizontally quickly at some point of growth.
"JoSk" mimics the native API of setTimeout and setInterval and supports CRON expressions. All queued tasks are synced between all running application instances via Redis, MongoDB, or a custom adapter.
The "JoSk" package is made for a variety of horizontally scaled apps, such as clusters, multi-servers, and multi-threaded Node.js instances, that are running either on the same or different machines or even different data centers. "JoSk ensures that the only single execution of each task occurs across all running instances of the application.
"JoSk" is not just for multi-instance apps. It seamlessly integrates with single-instance applications as well, showcasing its versatility and adaptability.
Note: JoSk is the server-only package.
ToC
- Main features
- Prerequisites
- Install as NPM package
- API
- Examples
- Important notes
- ~99% tests coverage
- Why it's named "JoSk"
- Support Section
Main features
- 🏢 Synchronize single task across multiple servers;
- 🔏 Read locking to avoid simultaneous task executions across complex infrastructure;
- 📦 Zero dependencies, written from scratch for top performance;
- 👨🔬 ~99% tests coverage;
- 💪 Bulletproof design, built-in retries, and "zombie" task recovery 🧟🔫.
Prerequisites
redis-server@>=5.0.0— Redis Server Version (if used with RedisAdapter)mongod@>=4.0.0— MongoDB Server Version (if used with MongoAdapter)node@>=14.20.0— Node.js version
Older releases compatibility
mongod@<4.0.0— usejosk@=1.1.0node@<14.20.0— usejosk@=3.0.2node@<8.9.0— usejosk@=1.1.0
Install:
npm install josk --save
// ES Module Style
import { JoSk, RedisAdapter, MongoAdapter } from 'josk';
// CommonJS
const { JoSk, RedisAdapter, MongoAdapter } = require('josk');
API:
Constructor options for JoSK, MongoAdapter, and RedisAdapter
new JoSk(opts)
opts.adapter{RedisAdapter|MongoAdapter} - [Required] Instance ofRedisAdapterorMongoAdapteror custom adapteropts.debug{Boolean} - [Optional] Enable debugging messages, useful during developmentopts.autoClear{Boolean} - [Optional] Remove (Clear) obsolete tasks (any tasks which are not found in the instance memory (runtime), but exists in the database). Obsolete tasks may appear in cases when it wasn't cleared from the database on process shutdown, and/or was removed/renamed in the app. Obsolete tasks may appear if multiple app instances running different codebase within the same database, and the task may not exist on one of the instances. Default:falseopts.zombieTime{Number} - [Optional] time in milliseconds, after this time - task will be interpreted as "zombie". This parameter allows to rescue task from "zombie mode" in case when:ready()wasn't called, exception during runtime was thrown, or caused by bad logic. WhileresetOnInitoption helps to make sure tasks aredoneon startup,zombieTimeoption helps to solve same issue, but during runtime. Default value is900000(15 minutes). It's not recommended to set this value to below60000(one minute)opts.minRevolvingDelay{Number} - [Optional] Minimum revolving delay — the minimum delay between tasks executions in milliseconds. Default:128opts.maxRevolvingDelay{Number} - [Optional] Maximum revolving delay — the maximum delay between tasks executions in milliseconds. Default:768opts.onError{Function} - [Optional] Informational hook, called instead of throwing exceptions. Default:false. Called with two arguments:title{String}details{Object}details.description{String}details.error{Mix}details.uid{String} - Internaluid, suitable for.clearInterval()and.clearTimeout()
opts.onExecuted{Function} - [Optional] Informational hook, called when task is finished. Default:false. Called with two arguments:uid{String} -uidpassed into.setImmediate(),.setTimeout(), orsetInterval()methodsdetails{Object}details.uid{String} - Internaluid, suitable for.clearInterval()and.clearTimeout()details.date{Date} - Execution timestamp as JS {Date}details.delay{Number} - Executiondelay(e.g.intervalfor.setInterval())details.timestamp{Number} - Execution timestamp as unix {Number}
new RedisAdapter(opts)
Since v5.0.0
opts.client{RedisClient} - [Required]RedisClientinstance, like one returned fromawait redis.createClient().connect()methodopts.prefix{String} - [Optional] use to create multiple named instancesopts.resetOnInit{Boolean} - [Optional] (use with caution) make sure all old tasks are completed during initialization. Useful for single-instance apps to clean up unfinished that occurred due to intermediate shutdown, reboot, or exception. Default:false
new MongoAdapter(opts)
Since v5.0.0
opts.db{Db} - [Required] Mongo'sDbinstance, like one returned fromMongoClient#db()methodopts.prefix{String} - [Optional] use to create multiple named instancesopts.lockCollectionName{String} - [Optional] By default all JoSk instances use the same__JobTasks__.lockcollection for lockingopts.resetOnInit{Boolean} - [Optional] (use with caution) make sure all old tasks are completed during initialization. Useful for single-instance apps to clean up unfinished that occurred due to intermediate shutdown, reboot, or exception. Default:false
Initialization
JoSk is storage-agnostic (since v4.0.0). It's shipped with Redis and MongoDB "adapters" out of the box, with option to extend its capabilities by creating and passing a custom adapter
Redis Adapter
JoSk has no dependencies, hence make sure redis NPM package is installed in order to support Redis Storage Adapter. RedisAdapter utilize basic set of commands SET, GET, DEL, EXISTS, HSET, HGETALL, and SCAN. RedisAdapter is compatible with all Redis-alike databases, and was well-tested with Redis and KeyDB
import { JoSk, RedisAdapter } from 'josk';
import { createClient } from 'redis';
const redisClient = await createClient({
url: 'redis://127.0.0.1:6379'
}).connect();
const jobs = new JoSk({
adapter: new RedisAdapter({
client: redisClient,
prefix: 'app-scheduler',
}),
onError(reason, details) {
// Use onError hook to catch runtime exceptions
// thrown inside scheduled tasks
console.log(reason, details.error);
}
});
MongoDB Adapter
JoSk has no dependencies, hence make sure mongodb NPM package is installed in order to support MongoDB Storage Adapter. Note: this package will add two new MongoDB collections per each new JoSk(). One collection for tasks and second for "Read
