multi-tasks 3.1.4 → 3.1.6

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.
package/README.md CHANGED
@@ -161,6 +161,12 @@ multiTasks({
161
161
  maxTaskRetries: 2,
162
162
  });
163
163
 
164
+ ```
165
+
166
+ ### Event broadcast
167
+
168
+ ```javascript
169
+
164
170
  //Example6, broadcast events between workers with helper.emit/helper.setListener
165
171
  multiTasks({
166
172
  initialTasks: alltasks,
@@ -199,15 +205,30 @@ multiTasks({
199
205
 
200
206
  ### Resuming
201
207
 
202
- If the execution is interrupted (e.g. a power outage), resume it by pointing to the task foldernothing else is needed, the config (including `processTask`) is restored from `task_config.json`:
208
+ If the execution is interrupted (e.g. a power outage), the simplest way to resume is to just re-run the same code`multiTasks(config)` detects the existing task folder and auto-resumes, re-running only the stuck tasks:
203
209
 
204
210
  ```javascript
205
211
 
206
- multiTasks.resume({ taskFolder: `/myworks/my_scan_tasks/my-task` }); //taskFolder: the full path of the existing task folder
212
+ //same command, same config as the interrupted run that's all
213
+ multiTasks(config);
214
+
215
+ ```
216
+
217
+ Or point `initialTasks` at the task folder — same effect:
218
+
219
+ ```javascript
220
+
221
+ multiTasks({ ...config, initialTasks: `/myworks/my_scan_tasks/my-task` });
207
222
 
208
223
  ```
209
224
 
210
- Re-running `multiTasks(config)` (or pointing `initialTasks` at the folder) auto-resumes too; passed config wins over the snapshot.
225
+ Or resume from the task folder alone the config (including `processTask`) is restored from `task_config.json`:
226
+
227
+ ```javascript
228
+
229
+ multiTasks.resume({ taskFolder: `/myworks/my_scan_tasks/my-task` }); //taskFolder: the full path of the existing task folder
230
+
231
+ ```
211
232
 
212
233
  **Note:** revived functions must be **self-contained** (no outer-scope variables; `require(...)` inside the body) — otherwise pass them again, they always win:
213
234
 
@@ -242,11 +263,13 @@ Unlike `retry_fails` (which re-runs only the failed tasks), `restart` re-runs **
242
263
 
243
264
  ### Changelog:
244
265
 
245
- - 3.1.4 Rewrite `multiTasks.resume`, `multiTasks.retry_fails` and `multiTasks.restart`
266
+ - 3.1.6 Fix silent task loss under heavy load with maxTaskRetries
267
+ - 3.1.5 Update README
268
+ - 3.1.4 Rewrite methods multiTasks.resume/retry_fails/restart
246
269
  - 3.1.3 Update README
247
270
  - 3.1.2 Update README
248
271
  - 3.1.1 Fix readme documentation
249
- - 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)
272
+ - 3.1.0 Support worker broadcast and system events; default numberOfWorkers is now "50%" of CPU cores
250
273
  - 3.0.4 numberOfWorkers accepts a percentage string of CPU cores, e.g. "50%"
251
274
  - 3.0.3 Support 'maxTaskRetries'
252
275
  - 3.0.2 Support 'taskTimeout'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multi-tasks",
3
- "version": "3.1.4",
3
+ "version": "3.1.6",
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": [
@@ -309,7 +309,7 @@ function runTask(config, subTask, subTaskLog){
309
309
  resultData = data;
310
310
  }).catch((ex)=>{
311
311
  errors.push({ex: serializeError(ex)});
312
- }).finally(()=>{
312
+ }).finally(async ()=>{
313
313
  let {startTimestamp} = subTaskLog;
314
314
  let endTimestamp = new Date()*1;
315
315
  let cost = endTimestamp - startTimestamp;
@@ -325,8 +325,14 @@ function runTask(config, subTask, subTaskLog){
325
325
  let retryCount = TaskMgr.incrementTaskRetry(subTask.subid);
326
326
  if(retryCount <= config.maxTaskRetries){
327
327
  console.warn(`[Task Retry] "${subTask.subid}" failed, retry (${retryCount}/${config.maxTaskRetries})`);
328
- TaskMgr.mvTask(subTask.subid, 'running', 'new', ()=>{});
329
328
  retried = true;
329
+ //等 rename 落盘再 resolve/请求新任务: fire-and-forget 的异步 rename 会随 worker 被
330
+ //autoClose 杀掉而消亡, 任务文件滞留 running 被静默丢弃(高负载偶发丢任务的根因, 勿回退)
331
+ try{
332
+ await TaskMgr.mvTaskPromise(subTask.subid, 'running', 'new');
333
+ }catch(newPath){
334
+ console.warn(`[Task Retry] "${subTask.subid}" failed to move back to new, left in running (recoverable via resume)`);
335
+ };
330
336
  };
331
337
  };
332
338
  TaskMgr.saveTaskLog(subTask.subid, subTaskLog);