multi-tasks 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +30 -36
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # multi-tasks
2
2
 
3
- Multi-tasks is a toolkit to manage long-term and large-scale parallel computing tasks. It manages progress and tasks based on the file system, which means that even if the host crashes, tasks can be resumed based on file records.
3
+ Multi-tasks is a toolkit to manage long-term and large-scale parallel computing tasks. Progress and tasks are stored on the file system, so tasks can be resumed even if the host crashes.
4
4
 
5
5
  **Zero dependencies:** multi-tasks has no runtime dependencies at all — it is built entirely on Node.js built-in modules (`cluster`, `fs`, `path`, `os`), so installing it adds nothing extra to your `node_modules`.
6
6
 
@@ -31,10 +31,10 @@ The API has three parts: the entry functions, the config options, and the `helpe
31
31
  - **`numberOfWorkers`** — how many worker processes run in parallel; a number, or a percentage string of CPU cores like `"50%"` (default).
32
32
  - **`taskTimeout`** — optional, milliseconds; an overdue task fails with a timeout error.
33
33
  - **`maxTaskRetries`** — optional, max times a failed task is auto-retried.
34
- - **`autoCloseAfterCompletion`** — set `false` if you create new tasks dynamically.
34
+ - **`autoCloseAfterCompletion`** — set `true` to kill workers and exit the process when no tasks are left; default is `false`, i.e. workers stay alive waiting for dynamically created tasks.
35
35
  - **`shouldTerminate(info)`** — return `true` to terminate the whole process.
36
36
  - **`setSysListener(event, payload, meta)`** — optional, handle custom system events (sent via `helper.emitSys`) on the master; `meta` has `fromWorkerId` and `fromWorkerPid`.
37
- - **`onFinish(report)`** — called once after all workers are done.
37
+ - **`onFinish(report)`** — called once after all workers exit (only when `autoCloseAfterCompletion` is `true`); `report` is an empty object for now.
38
38
 
39
39
  **Task helper** (the `helper` object passed as the second argument of `processTask`):
40
40
 
@@ -49,7 +49,7 @@ The API has three parts: the entry functions, the config options, and the `helpe
49
49
  //see examples/example0
50
50
  let multiTasks = require('multi-tasks').multiTasks;
51
51
 
52
- //Step1, create your tasks that need to be executed simultaneously as an array.
52
+ //Step1, create the tasks to run in parallel as an array.
53
53
  let alltasks = [];
54
54
  for(let i=0;i<50;i++){
55
55
  alltasks.push({
@@ -58,7 +58,7 @@ for(let i=0;i<50;i++){
58
58
  });
59
59
  };
60
60
 
61
- //Step2, provide a function to process a certain sub-task and return the result data
61
+ //Step2, provide a function that processes each sub-task and returns the result
62
62
  let processTask = (task, helper)=>{
63
63
  let {taskCount} = task;//get your task data
64
64
 
@@ -72,12 +72,12 @@ let processTask = (task, helper)=>{
72
72
  multiTasks({
73
73
  initialTasks: alltasks,
74
74
  processTask,
75
- taskRootFolder: `../examples-tmp-data/example0`, //a directory to store progress and results files, you can check the progress here
75
+ taskRootFolder: `../examples-tmp-data/example0`, //a directory to store progress and result files; you can check the progress here
76
76
  taskId: 'my-task',
77
77
  numberOfWorkers: 3, //how many workers are working in parallel
78
78
  //taskTimeout: 30000, //optional, in milliseconds, an overdue task is treated as failed with a timeout error
79
79
  //maxTaskRetries: 2, //optional, auto-retry a failed task (worker crash, processTask error, or timeout); retried tasks go back to the queue
80
- //autoCloseAfterCompletion: true, //if you have dynamically generated new tasks, put this as false
80
+ //autoCloseAfterCompletion: true, //set true to exit the process when all tasks are done; keep it false (default) if you create new tasks dynamically
81
81
  shouldTerminate:(info)=>{
82
82
  //return true if you need to terminate the whole process
83
83
  },
@@ -91,6 +91,8 @@ multiTasks({
91
91
  ### More about the task processing function
92
92
 
93
93
  ```javascript
94
+ //Examples 1-3 below are independent variants of processTask, use one at a time.
95
+
94
96
  //Example1, return a promise for async processes,
95
97
  // you can return a promise or a non-promise result,
96
98
  // all result data can be found in the results/succ folder
@@ -127,21 +129,26 @@ let processTask = (task, helper)=>{
127
129
  let processTask = (task, helper)=>{
128
130
  let {taskCount} = task;
129
131
 
130
- //This is the demo of exceptions/errors, they will be captured and saved in the results/errors folder
132
+ //Demo of exceptions/errors: they are captured and saved in the results/errors folder
131
133
  if(taskCount===3) throw 'exception';
132
134
  if(taskCount===4) return Promise.reject({err:'a test error'});//use Promise.reject method
133
- if(taskCount===5) aaa = bbb;//this undefined exception will be captured by multi-tasks
135
+ if(taskCount===5) aaa = bbb;//this ReferenceError will be captured by multi-tasks
134
136
 
135
137
  return {data:'succ'};
136
138
  }
137
139
 
138
- //Example5, auto-retry a failed task:
139
- // when a task fails - its worker process crashes, processTask throws
140
- // or rejects, or it exceeds taskTimeout - it is sent back to the
141
- // queue and retried, at most maxTaskRetries times; when the limit
142
- // is reached it lands in finished_with_errors (crash:
143
- // {type:'worker_crash'}, timeout: {type:'timeout'}, processTask
144
- // error: the original error data)
140
+ //Example4, timeout: a task that does not finish within taskTimeout is
141
+ // treated as failed with a timeout error
142
+ multiTasks({
143
+ initialTasks: alltasks,
144
+ processTask,
145
+ taskRootFolder: `../examples-tmp-data/example-timeout`,
146
+ taskId: 'my-task',
147
+ numberOfWorkers: 3,
148
+ taskTimeout: 30000,
149
+ });
150
+
151
+ //Example5, auto-retry a failed task with maxTaskRetries
145
152
  multiTasks({
146
153
  initialTasks: alltasks,
147
154
  processTask,
@@ -151,13 +158,7 @@ multiTasks({
151
158
  maxTaskRetries: 2,
152
159
  });
153
160
 
154
- //Example6, broadcast events between workers:
155
- // a worker emits an event and the master relays it to every worker
156
- // (best-effort, runtime only - not persisted, not replayed on
157
- // resume); by default the sender also receives its own event, pass
158
- // {includingMe: false} to exclude it; each event keeps only one
159
- // listener per worker process, so calling setListener on every
160
- // task is safe
161
+ //Example6, broadcast events between workers with helper.emit/helper.setListener
161
162
  multiTasks({
162
163
  initialTasks: alltasks,
163
164
  taskRootFolder: `../examples-tmp-data/example-broadcast`,
@@ -172,12 +173,7 @@ multiTasks({
172
173
  },
173
174
  });
174
175
 
175
- //Example7, system events from a worker to the master:
176
- // helper.emitSys sends a system event that the master consumes
177
- // itself (not relayed to workers); the built-in event
178
- // TERMINATE_ALL_WORKERS force-kills all workers and exits the
179
- // master (unfinished tasks stay for resume); any other event is
180
- // passed to config.setSysListener on the master
176
+ //Example7, system events from a worker to the master with helper.emitSys
181
177
  multiTasks({
182
178
  initialTasks: alltasks,
183
179
  taskRootFolder: `../examples-tmp-data/example-sysevent`,
@@ -200,12 +196,12 @@ multiTasks({
200
196
 
201
197
  ### Resuming
202
198
 
203
- Sometimes the task execution is interrupted due to some reasons (such as power outage), you can resume the execution like this
199
+ If the execution is interrupted (e.g. a power outage), resume it like this:
204
200
 
205
201
  ```javascript
206
202
 
207
203
  multiTasks({
208
- initialTasks: `/myworks/my_scan_tasks/`, //Point 'initialTasks' to the interrupted task directory, multi-tasks will read the tasks in the 'new' folder and initialize them to 'initialTasks' and then continue execution
204
+ initialTasks: `/myworks/my_scan_tasks/`, //point 'initialTasks' to the interrupted task directory; multi-tasks reads the tasks in its 'new' folder and continues execution
209
205
  ...
210
206
  ...//Other configurations remain unchanged
211
207
  ...
@@ -213,12 +209,10 @@ multiTasks({
213
209
 
214
210
  ```
215
211
 
216
- ### Testing:
217
-
218
- The usage patterns documented above are covered by automated tests (unit tests in `test/`, end-to-end tests in `teste2e/`). The e2e suite runs the API in real child processes with a mixed workload — successful tasks (both promise and non-promise results), planned failures (rejected promises and thrown exceptions), dynamically created tasks via `helper.createNewTasks`, and workers that crash randomly — then resumes repeatedly and verifies that every task lands exactly one result in `results/succ` or `results/errors`.
219
-
220
212
  ### Changelog:
221
213
 
214
+ - 3.1.3 Update README
215
+ - 3.1.2 Update README
222
216
  - 3.1.1 Fix readme documentation
223
217
  - 3.1.0 Support worker broadcast ('helper.emit' and 'helper.setListener') and system events ('helper.emitSys' and 'setSysListener', with built-in 'TERMINATE_ALL_WORKERS'); default numberOfWorkers is now "50%" of CPU cores (was core count minus 1)
224
218
  - 3.0.4 numberOfWorkers accepts a percentage string of CPU cores, e.g. "50%"
@@ -263,4 +257,4 @@ The usage patterns documented above are covered by automated tests (unit tests i
263
257
 
264
258
  ### License:
265
259
 
266
- [MIT](https://opensource.org/license/MIT) (see [LICENSE](LICENSE))
260
+ [MIT](https://opensource.org/license/MIT)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multi-tasks",
3
- "version": "3.1.1",
3
+ "version": "3.1.3",
4
4
  "description": "Multi-process task scheduling based on Node.js cluster, with crash resume and failed-task restart support",
5
5
  "main": "index.js",
6
6
  "files": [