Skip to content

Commit cfa8041

Browse files
committed
📔 Documentation update
1 parent 4d6a3b4 commit cfa8041

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

README.md

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@
55

66
# JoSk
77

8-
"JoSk" is a Node.js task manager for horizontally scaled apps, apps planning horizontal scaling, and apps that would need to scale horizontally in the future with ease.
8+
"JoSk" is a Node.js task manager for horizontally scaled apps, apps planning for horizontal scaling, and apps that would need to scale horizontally in the future with ease.
99

10-
"JoSk" follows `setTimeout` and `setInterval` methods native API. Optionally tasks can get scheduled using [CRON expressions](https://github.com/veliovgroup/josk?tab=readme-ov-file#cron). All queued tasks are synced between all running application instances via Redis, MongoDB, or [custom adapter](https://github.com/veliovgroup/josk/blob/master/docs/adapter-api.md).
10+
"JoSk" mimics the native API of `setTimeout` and `setInterval`. Tasks also can get scheduled using [CRON expressions](https://github.com/veliovgroup/josk?tab=readme-ov-file#cron). All queued tasks are synced between all running application instances via Redis, MongoDB, or [custom adapter](https://github.com/veliovgroup/josk/blob/master/docs/adapter-api.md).
1111

12-
"JoSk" package support different horizontally scaled apps as clusters, multi-server, and multi-threaded Node.js instances. That are running either on the same or different machines or different data-centers. "JoSk" ensures that the only single execution of each *task* occurs across all running instances of the application.
12+
"JoSk" package made for different variety of horizontally scaled apps as clusters, multi-server, 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.
13+
14+
Although "JoSk" is made with multi-instance apps in mind, — it works on a single-instance applications seamlessly.
1315

1416
__Note: JoSk is the server-only package.__
1517

1618
## ToC
1719

20+
- [Main features](https://github.com/veliovgroup/josk?tab=readme-ov-file#main-features)
1821
- [Prerequisites](https://github.com/veliovgroup/josk?tab=readme-ov-file#prerequisites)
1922
- [Install](https://github.com/veliovgroup/josk?tab=readme-ov-file#install) as [NPM package](https://www.npmjs.com/package/josk)
2023
- [API](https://github.com/veliovgroup/josk?tab=readme-ov-file#api)
@@ -33,12 +36,15 @@ __Note: JoSk is the server-only package.__
3336
- [Clean up stale tasks](https://github.com/veliovgroup/josk?tab=readme-ov-file#clean-up-old-tasks)
3437
- [MongoDB connection options](https://github.com/veliovgroup/josk?tab=readme-ov-file#mongodb-connection-fine-tuning)
3538
- [Meteor.js](https://github.com/veliovgroup/josk/blob/master/docs/meteor.md)
39+
- [Important notes](https://github.com/veliovgroup/josk?tab=readme-ov-file#notes)
3640
- [~99% tests coverage](https://github.com/veliovgroup/josk?tab=readme-ov-file#running-tests)
41+
- [Why it's named "JoSk"](https://github.com/veliovgroup/josk?tab=readme-ov-file#why-josk)
42+
- [Support Section](https://github.com/veliovgroup/josk?tab=readme-ov-file#support-our-open-source-contribution)
3743

3844
## Main features
3945

4046
- 🏢 Synchronize single task across multiple servers;
41-
- 🔏 Collection locking to avoid simultaneous task executions across complex infrastructure;
47+
- 🔏 Read locking to avoid simultaneous task executions across complex infrastructure;
4248
- 📦 Zero dependencies, written from scratch for top performance;
4349
- 👨‍🔬 ~99% tests coverage;
4450
- 💪 Bulletproof design, built-in retries, and "zombie" task recovery 🧟🔫.
@@ -69,14 +75,6 @@ import { JoSk, RedisAdapter, MongoAdapter } from 'josk';
6975
const { JoSk, RedisAdapter, MongoAdapter } = require('josk');
7076
```
7177

72-
## Notes
73-
74-
- This package is perfect when you have multiple horizontally scaled servers for load-balancing, durability, an array of micro-services or any other solution with multiple running copies of code running repeating tasks that needs to run only once per application/cluster, not per server/instance;
75-
- Limitation — task must be run not often than once per two seconds (from 2 to ∞ seconds). Example tasks: [Email](https://www.npmjs.com/package/mail-time), SMS queue, Long-polling requests, Periodical application logic operations or Periodical data fetch, sync, and etc;
76-
- Accuracy — Delay of each task depends on storage and "de-synchronization delay". Trusted time-range of execution period is `task_delay ± (256 + Storage_Request_Delay)`. That means this package won't fit when you need to run a task with very certain delays. For other cases, if `±256 ms` delays are acceptable - this package is the great solution;
77-
- Use `opts.minRevolvingDelay` and `opts.maxRevolvingDelay` to set the range for *random* delays between executions. Revolving range acts as a safety control to make sure different servers __not__ picking the same task at the same time. Default values (`128` and `768`) are the best for 3-server setup (*the most common topology*). Tune these options to match needs of your project. Higher `opts.minRevolvingDelay` will reduce storage read/writes;
78-
- This package implements "Read Locking" via "RedLock" for Redis and dedicated `.lock` collection for MongoDB.
79-
8078
## API:
8179

8280
`new JoSk({opts})`:
@@ -88,8 +86,8 @@ const { JoSk, RedisAdapter, MongoAdapter } = require('josk');
8886
- `opts.prefix` {*String*} - [Optional] use to create multiple named instances
8987
- `opts.debug` {*Boolean*} - [Optional] Enable debugging messages, useful during development
9088
- `opts.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: `false`
91-
- `opts.resetOnInit` {*Boolean*} - [Optional] (*__use with caution__*) make sure all old tasks is completed before setting a new one. Useful when you run a single instance of an app, or multiple app instances on __one__ machine, in case machine was reloaded during running task and task is unfinished
92-
- `opts.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. While `resetOnInit` option helps to make sure tasks are `done` on startup, `zombieTime` option helps to solve same issue, but during runtime. Default value is `900000` (*15 minutes*). It's not recommended to set this value to less than a minute (*60000ms*)
89+
- `opts.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`
90+
- `opts.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. While `resetOnInit` option helps to make sure tasks are `done` on startup, `zombieTime` option helps to solve same issue, but during runtime. Default value is `900000` (*15 minutes*). It's not recommended to set this value to below `60000` (*one minute*)
9391
- `opts.minRevolvingDelay` {*Number*} - [Optional] Minimum revolving delay — the minimum delay between tasks executions in milliseconds. Default: `128`
9492
- `opts.maxRevolvingDelay` {*Number*} - [Optional] Maximum revolving delay — the maximum delay between tasks executions in milliseconds. Default: `768`
9593
- `opts.onError` {*Function*} - [Optional] Informational hook, called instead of throwing exceptions. Default: `false`. Called with two arguments:
@@ -108,11 +106,11 @@ const { JoSk, RedisAdapter, MongoAdapter } = require('josk');
108106

109107
### Initialization
110108

111-
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](https://github.com/veliovgroup/josk/blob/master/docs/adapter-api.md)
109+
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](https://github.com/veliovgroup/josk/blob/master/docs/adapter-api.md)
112110

113111
#### Redis Adapter
114112

115-
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, was well-tested with [Redis](https://redis.io/) and [KeyDB](https://docs.keydb.dev/)
113+
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](https://redis.io/) and [KeyDB](https://docs.keydb.dev/)
116114

117115
```js
118116
import { JoSk, RedisAdapter } from 'josk';
@@ -130,7 +128,7 @@ const jobs = new JoSk({
130128

131129
#### MongoDB Adapter
132130

133-
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({ prefix })`. One collection for tasks and another one for "Read Locking" with `.lock` suffix
131+
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({ prefix })`. One collection for tasks and second for "Read Locking" with `.lock` suffix
134132

135133
```js
136134
import { JoSk, MongoAdapter } from 'josk';
@@ -184,8 +182,9 @@ jobs.setInterval(asyncAwaitTask, 30 * 60 * 1000, 'asyncAwaitTask30m'); // every
184182
### `setInterval(func, delay, uid)`
185183

186184
- `func` {*Function*} - Function to call on schedule
187-
- `delay` {*Number*} - Delay for first run and interval between further executions in milliseconds
185+
- `delay` {*Number*} - Delay for the first run and interval between further executions in milliseconds
188186
- `uid` {*String*} - Unique app-wide task id
187+
- Returns: {*String*}
189188

190189
*Set task into interval execution loop.* `ready()` *callback is passed as the first argument into a task function.*
191190

@@ -231,7 +230,7 @@ jobs.setInterval(syncTask, 60 * 60 * 1000, 'syncTask1h'); // will execute every
231230
jobs.setInterval(asyncAwaitTask, 60 * 60 * 1000, 'asyncAwaitTask1h'); // will execute every hour
232231
```
233232

234-
In this example, we're assuming to have long running task, executed in a loop without delay, but after full execution:
233+
In the next example, a long running task is executed in a loop without delay after the full execution:
235234

236235
```js
237236
const longRunningAsyncTask = function (ready) {
@@ -240,8 +239,13 @@ const longRunningAsyncTask = function (ready) {
240239
ready(); // <-- Always run `ready()`, even if call was unsuccessful
241240
} else {
242241
anotherCall(result.data, ['param'], (error, response) => {
242+
if (error) {
243+
ready(); // <-- Always run `ready()`, even if call was unsuccessful
244+
return;
245+
}
246+
243247
waitForSomethingElse(response, () => {
244-
ready(); // <-- End of full execution
248+
ready(); // <-- End of the full execution
245249
});
246250
});
247251
}
@@ -253,11 +257,12 @@ jobs.setInterval(longRunningAsyncTask, 0, 'longRunningAsyncTask'); // run in a l
253257

254258
### `setTimeout(func, delay, uid)`
255259

256-
- `func` {*Function*} - Function to call on schedule
260+
- `func` {*Function*} - Function to call after `delay`
257261
- `delay` {*Number*} - Delay in milliseconds
258262
- `uid` {*String*} - Unique app-wide task id
263+
- Returns: {*String*}
259264

260-
*Set task into timeout execution.* `setTimeout` *is useful for cluster - when you need to make sure task executed only once.* `ready()` *callback is passed as the first argument into a task function.*
265+
*Run a task after delay in ms.* `setTimeout` *is useful for cluster - when you need to make sure task executed only once.* `ready()` *callback is passed as the first argument into a task function.*
261266

262267
```js
263268
const syncTask = function (ready) {
@@ -292,6 +297,7 @@ jobs.setTimeout(asyncAwaitTask, 60 * 1000, 'asyncAwaitTaskIn1m'); // will run on
292297

293298
- `func` {*Function*} - Function to execute
294299
- `uid` {*String*} - Unique app-wide task id
300+
- Returns: {*String*}
295301

296302
*Immediate execute the function, and only once.* `setImmediate` *is useful for cluster - when you need to execute function immediately and only once across all servers.* `ready()` *is passed as the first argument into the task function.*
297303

@@ -473,10 +479,21 @@ const options = {
473479
MongoClient.connect('mongodb://url', options, (error, client) => {
474480
// To avoid "DB locks" — it's a good idea to use separate DB from "main" application DB
475481
const db = client.db('dbName');
476-
const jobs = new JoSk({ db });
482+
const jobs = new JoSk({
483+
adapter: MongoAdapter,
484+
db: db,
485+
});
477486
});
478487
```
479488

489+
## Notes
490+
491+
- This package is perfect when you have multiple horizontally scaled servers for load-balancing, durability, an array of micro-services or any other solution with multiple running copies of code running repeating tasks that needs to run only once per application/cluster, not per server/instance;
492+
- Limitation — task must be run not often than once per two seconds (from 2 to ∞ seconds). Example tasks: [Email](https://www.npmjs.com/package/mail-time), SMS queue, Long-polling requests, Periodical application logic operations or Periodical data fetch, sync, and etc;
493+
- Accuracy — Delay of each task depends on storage and "de-synchronization delay". Trusted time-range of execution period is `task_delay ± (256 + Storage_Request_Delay)`. That means this package won't fit when you need to run a task with very precise delays. For other cases, if `±256 ms` delays are acceptable - this package is the great solution;
494+
- Use `opts.minRevolvingDelay` and `opts.maxRevolvingDelay` to set the range for *random* delays between executions. Revolving range acts as a safety control to make sure different servers __not__ picking the same task at the same time. Default values (`128` and `768`) are the best for 3-server setup (*the most common topology*). Tune these options to match needs of your project. Higher `opts.minRevolvingDelay` will reduce storage read/writes;
495+
- This package implements "Read Locking" via "RedLock" for Redis and dedicated `.lock` collection for MongoDB.
496+
480497
## Running Tests
481498

482499
1. Clone this package

docs/meteor.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
NPM `josk` package can be used in Meteor environment just perfectly fine since it's server-only Node.js package.
44

5-
If Meteor.js packages are preferred in you project/environment follow this document to install JoSk as `ostrio:cron-jobs` [Atmosphere](https://atmospherejs.com/ostrio/cron-jobs) or [Packosphere](https://packosphere.com/ostrio/cron-jobs) package
5+
If Meteor.js packages are preferred in your project/environment follow this document to install JoSk as `ostrio:cron-jobs` [Atmosphere](https://atmospherejs.com/ostrio/cron-jobs) or [Packosphere](https://packosphere.com/ostrio/cron-jobs) package
66

77
## Install
88

@@ -61,7 +61,7 @@ const setCron = (uniqueName, cronTask, task) => {
6161
return jobsCron.setTimeout(function (done) {
6262
done(() => {
6363
task(); // <- Execute task
64-
createCronTask(uniqueName, cronTask, task); // <- Create task for the next iteration
64+
setCron(uniqueName, cronTask, task); // <- Create task for the next iteration
6565
});
6666
}, timeout, uniqueName);
6767
};

0 commit comments

Comments
 (0)