multi-tasks 2.0.8 → 2.1.0
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 +10 -17
- package/examples/example0/run-readme.js +3 -3
- package/examples/example0/run.js +1 -1
- package/examples/example0/runm.mjs +53 -0
- package/package.json +1 -1
- package/test/test_resume/step1_start_and_crash.js +1 -1
- package/test/test_resume/test.sh +1 -0
- package/workers/Multithread.js +23 -6
- package/workers/TaskMgr.js +24 -8
package/README.md
CHANGED
|
@@ -14,8 +14,7 @@ How to use:
|
|
|
14
14
|
let multiTasks = require('multi-tasks').multiTasks;
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
//Step1,
|
|
18
|
-
// provide them as an array, multi-tasks will automatically split them and execute.
|
|
17
|
+
//Step1, create your tasks that need to be executed simultaneously as an array.
|
|
19
18
|
let alltasks = [];
|
|
20
19
|
for(let i=0;i<50;i++){
|
|
21
20
|
alltasks.push({
|
|
@@ -26,9 +25,12 @@ for(let i=0;i<50;i++){
|
|
|
26
25
|
|
|
27
26
|
//Step2, provide a function to process a certain sub-task and return the result data
|
|
28
27
|
let processTask = (task, helper)=>{
|
|
29
|
-
let {taskCount} = task
|
|
28
|
+
let {taskCount} = task;//get your task data
|
|
29
|
+
|
|
30
|
+
//Run your processing logic here...
|
|
30
31
|
|
|
31
|
-
return
|
|
32
|
+
//then return the result as a plain javascript object or an async promise
|
|
33
|
+
return 'result data';
|
|
32
34
|
};
|
|
33
35
|
|
|
34
36
|
//Step3, run!
|
|
@@ -78,7 +80,8 @@ let processTask = (task, helper)=>{
|
|
|
78
80
|
|
|
79
81
|
|
|
80
82
|
if(taskCount % 2 === 0){
|
|
81
|
-
|
|
83
|
+
//create a new task if needed
|
|
84
|
+
helper.createNewTasks({
|
|
82
85
|
msg:'a new task'
|
|
83
86
|
});
|
|
84
87
|
return;
|
|
@@ -104,22 +107,12 @@ let processTask = (task, helper)=>{
|
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
|
|
107
|
-
//Example4, dynamically create a new task while processing
|
|
108
|
-
let processTask = (task, helper)=>{
|
|
109
|
-
let {taskCount} = task;
|
|
110
|
-
|
|
111
|
-
if(taskCount % 2 === 0){
|
|
112
|
-
helper.createNewTasks({//create a new task if needed
|
|
113
|
-
msg:'a new task'
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return {data:'succ'};
|
|
118
|
-
}
|
|
119
110
|
```
|
|
120
111
|
|
|
121
112
|
Changelog:
|
|
122
113
|
|
|
114
|
+
- 2.1.0 Add a new output directory "log" where you can view the process time of each subtask
|
|
115
|
+
- 2.0.9 Update readme examples
|
|
123
116
|
- 2.0.8 Update readme examples
|
|
124
117
|
- 2.0.7 Update changelog
|
|
125
118
|
- 2.0.6 Update readme, remove failed examples
|
|
@@ -13,7 +13,7 @@ for(let i=0;i<50;i++){
|
|
|
13
13
|
let processTask = (task, helper)=>{
|
|
14
14
|
let {taskCount} = task;
|
|
15
15
|
|
|
16
|
-
return '
|
|
16
|
+
return 'result data';
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
//Step2.1, or return a promise
|
|
@@ -76,10 +76,10 @@ let processTask = (task, helper)=>{
|
|
|
76
76
|
|
|
77
77
|
//Step3, run!
|
|
78
78
|
multiTasks.start({
|
|
79
|
-
|
|
79
|
+
initialTasks: alltasks,
|
|
80
80
|
processTask,
|
|
81
81
|
taskRootFolder: `../examples-tmp-data/example0`, //a directory to store progress and results files, you can check the progress here
|
|
82
|
-
taskId: 'my-task',
|
|
82
|
+
taskId: 'my-readme-task',
|
|
83
83
|
numberOfWorkers: 3, //Assign how many workers are working in parallel
|
|
84
84
|
//autoCloseAfterCompletion: true, //if you have dynamically generated new tasks, put this as false
|
|
85
85
|
onFinish: (report)=>{
|
package/examples/example0/run.js
CHANGED
|
@@ -44,7 +44,7 @@ multiTasks({
|
|
|
44
44
|
initialTasks: alltasks,
|
|
45
45
|
processTask,
|
|
46
46
|
taskRootFolder: `../examples-tmp-data/example0`, //a directory to store progress and results files, you can check the progress here
|
|
47
|
-
taskId: 'my-task',
|
|
47
|
+
taskId: 'my-task' + Math.random(),
|
|
48
48
|
numberOfWorkers: 3, //Assign how many workers are working in parallel
|
|
49
49
|
//autoCloseAfterCompletion: true,
|
|
50
50
|
onFinish: (report)=>{
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {multiTasks} from '../../index.js';
|
|
2
|
+
|
|
3
|
+
//Step1, If you have tasks that need to be executed simultaneously, please provide them as an array, multi-tasks will automatically split them and execute.
|
|
4
|
+
let alltasks = [];
|
|
5
|
+
for(let i=0;i<50;i++){
|
|
6
|
+
let task_props = {
|
|
7
|
+
index: i,
|
|
8
|
+
name: `task-${i}`,
|
|
9
|
+
description: `This prop is for a subtask`
|
|
10
|
+
};
|
|
11
|
+
alltasks.push(task_props);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//Step2, Provide a process function to handle a certain sub-task and return the result data
|
|
15
|
+
let processTask = (task, helper)=>{
|
|
16
|
+
//console.log('this is the subtask data you created above:', task);
|
|
17
|
+
let {taskCount} = task;
|
|
18
|
+
|
|
19
|
+
console.log(taskCount)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
//This is the demo of exceptions/errors, they will be captured and saved in the results/errors folder
|
|
23
|
+
if(taskCount===3) throw 'exception';
|
|
24
|
+
if(taskCount===4) return Promise.reject({err:'a test error'});
|
|
25
|
+
if(taskCount===5) aaa = bbb;
|
|
26
|
+
|
|
27
|
+
if(taskCount===6) return 'a result which is not a promise'; //Return a non-promise result is also OK
|
|
28
|
+
|
|
29
|
+
//by default, you should return a promise, all returned data can be found in the results/succ folder
|
|
30
|
+
return new Promise((resolve, reject)=>{
|
|
31
|
+
setTimeout(()=>{
|
|
32
|
+
if(taskCount % 2 === 0)helper.createNewTasks({//
|
|
33
|
+
msg:'a new task'
|
|
34
|
+
});
|
|
35
|
+
taskCount === 2 ? reject('a rejected error') : resolve({
|
|
36
|
+
message: 'this is a result from a demo, random data=' + Math.random()
|
|
37
|
+
});
|
|
38
|
+
}, 10 * Math.random())
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//Step3, run!
|
|
43
|
+
multiTasks({
|
|
44
|
+
initialTasks: alltasks,
|
|
45
|
+
processTask,
|
|
46
|
+
taskRootFolder: `../examples-tmp-data/example0`, //a directory to store progress and results files, you can check the progress here
|
|
47
|
+
taskId: 'my-task',
|
|
48
|
+
numberOfWorkers: 3, //Assign how many workers are working in parallel
|
|
49
|
+
//autoCloseAfterCompletion: true,
|
|
50
|
+
onFinish: (report)=>{
|
|
51
|
+
console.log('finish callback', report);
|
|
52
|
+
}
|
|
53
|
+
});
|
package/package.json
CHANGED
package/test/test_resume/test.sh
CHANGED
package/workers/Multithread.js
CHANGED
|
@@ -156,9 +156,12 @@ function subWorker(){
|
|
|
156
156
|
let sendMsg = (msg)=>{
|
|
157
157
|
worker.send(msg);
|
|
158
158
|
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
let subTaskLog = {
|
|
160
|
+
taskCount,
|
|
161
|
+
startTimestamp
|
|
162
|
+
};
|
|
163
|
+
runTask(config, subTask, subTaskLog, sendMsg).then((tasklog)=>{
|
|
164
|
+
let {cost, startTimestamp, endTimestamp} = tasklog;
|
|
162
165
|
|
|
163
166
|
console.log(`[Task Finished] "${config.masterTaskId}"."${subTask.subid}".`, getDateTimeTxt(), `cost=${cost}ms`)
|
|
164
167
|
}).then(()=>{
|
|
@@ -173,7 +176,7 @@ function subWorker(){
|
|
|
173
176
|
worker.send(MSG_REQUEST_NEW_TASK);//request new task
|
|
174
177
|
|
|
175
178
|
};
|
|
176
|
-
function runTask(config, subTask, sendMsg){
|
|
179
|
+
function runTask(config, subTask, subTaskLog, sendMsg){
|
|
177
180
|
return new Promise((resolve)=>{
|
|
178
181
|
let resultPromise = Promise.resolve({});
|
|
179
182
|
let resultData;
|
|
@@ -185,6 +188,7 @@ function runTask(config, subTask, sendMsg){
|
|
|
185
188
|
params
|
|
186
189
|
});
|
|
187
190
|
};
|
|
191
|
+
TaskMgr.saveTaskLog(subTask.subid, subTaskLog);
|
|
188
192
|
try{
|
|
189
193
|
resultPromise = USER_CONFIG.processTask(subTask, helper);//rewrite this method in subclass
|
|
190
194
|
}catch(e){
|
|
@@ -198,11 +202,24 @@ function runTask(config, subTask, sendMsg){
|
|
|
198
202
|
if(typeof ex !== 'string') ex = ex.toString();
|
|
199
203
|
errors.push({ex});
|
|
200
204
|
}).finally(()=>{
|
|
205
|
+
let {startTimestamp} = subTaskLog;
|
|
206
|
+
let endTimestamp = new Date()*1;
|
|
207
|
+
let cost = endTimestamp - startTimestamp;
|
|
208
|
+
subTaskLog = {
|
|
209
|
+
...subTaskLog,
|
|
210
|
+
endTimestamp,
|
|
211
|
+
cost
|
|
212
|
+
};
|
|
201
213
|
let hasError = errors.length > 0;
|
|
202
|
-
if(hasError)console.log('hasError=====', hasError, errors)
|
|
214
|
+
if(hasError)console.log('hasError=====', hasError, errors);
|
|
215
|
+
TaskMgr.saveTaskLog(subTask.subid, subTaskLog);
|
|
203
216
|
TaskMgr.saveTaskResult(subTask.subid, hasError, hasError ? errors : resultData);
|
|
204
217
|
TaskMgr.mvTask(subTask.subid, 'running',(hasError ? 'finished_with_errors':'finished'), (newPath)=>{
|
|
205
|
-
resolve(
|
|
218
|
+
resolve({
|
|
219
|
+
startTimestamp,
|
|
220
|
+
endTimestamp,
|
|
221
|
+
cost
|
|
222
|
+
});
|
|
206
223
|
});
|
|
207
224
|
});
|
|
208
225
|
});
|
package/workers/TaskMgr.js
CHANGED
|
@@ -43,19 +43,21 @@ const TaskMgr = {
|
|
|
43
43
|
};
|
|
44
44
|
//let taskfolder = pathutil.parse(__filename).dir;
|
|
45
45
|
//let taskFolder = pathutil.resolve(taskfolder, `./tasks/${masterTaskId}`);
|
|
46
|
-
progressRootFolder = pathutil.resolve(taskFolder, './progress');
|
|
47
|
-
resultsRootFolder = pathutil.resolve(taskFolder, './results');
|
|
46
|
+
const progressRootFolder = pathutil.resolve(taskFolder, './progress');
|
|
47
|
+
const resultsRootFolder = pathutil.resolve(taskFolder, './results');
|
|
48
|
+
const logsRootFolder = pathutil.resolve(taskFolder, './logs');
|
|
48
49
|
|
|
49
|
-
taskFolderNew = pathutil.resolve(progressRootFolder, './new');
|
|
50
|
-
taskFolderRunning = pathutil.resolve(progressRootFolder, './running');
|
|
51
|
-
taskFolderFinished = pathutil.resolve(progressRootFolder, './finished');
|
|
52
|
-
taskFolderFailed= pathutil.resolve(progressRootFolder, './finished_with_errors');
|
|
50
|
+
const taskFolderNew = pathutil.resolve(progressRootFolder, './new');
|
|
51
|
+
const taskFolderRunning = pathutil.resolve(progressRootFolder, './running');
|
|
52
|
+
const taskFolderFinished = pathutil.resolve(progressRootFolder, './finished');
|
|
53
|
+
const taskFolderFailed= pathutil.resolve(progressRootFolder, './finished_with_errors');
|
|
53
54
|
|
|
54
|
-
taskFolderResult = pathutil.resolve(resultsRootFolder, './succ');
|
|
55
|
-
taskFolderResultFailed = pathutil.resolve(resultsRootFolder, './errors');
|
|
55
|
+
const taskFolderResult = pathutil.resolve(resultsRootFolder, './succ');
|
|
56
|
+
const taskFolderResultFailed = pathutil.resolve(resultsRootFolder, './errors');
|
|
56
57
|
//let mainRptFolder = pathutil.resolve(taskfolder, './report');
|
|
57
58
|
|
|
58
59
|
//makeDir.sync(mainRptFolder);
|
|
60
|
+
makeDir.sync(logsRootFolder);
|
|
59
61
|
makeDir.sync(taskFolderNew);
|
|
60
62
|
makeDir.sync(taskFolderRunning);
|
|
61
63
|
makeDir.sync(taskFolderFinished);
|
|
@@ -68,6 +70,7 @@ const TaskMgr = {
|
|
|
68
70
|
taskFolder,
|
|
69
71
|
progressRootFolder,
|
|
70
72
|
resultsRootFolder,
|
|
73
|
+
logsRootFolder,
|
|
71
74
|
|
|
72
75
|
taskFolderNew,
|
|
73
76
|
taskFolderRunning,
|
|
@@ -208,6 +211,19 @@ const TaskMgr = {
|
|
|
208
211
|
fcontent = JSON.stringify(data);
|
|
209
212
|
};
|
|
210
213
|
fs.writeFileSync(fpath, fcontent);
|
|
214
|
+
},
|
|
215
|
+
saveTaskLog:(subid, log)=>{
|
|
216
|
+
let {logsRootFolder} = main_config;
|
|
217
|
+
let folder = logsRootFolder;
|
|
218
|
+
let fpath = pathutil.resolve(folder, `${subid}.json`);
|
|
219
|
+
let fcontent;
|
|
220
|
+
log.subid = subid;
|
|
221
|
+
if(typeof log === 'undefined') {
|
|
222
|
+
fcontent = '';
|
|
223
|
+
}else{
|
|
224
|
+
fcontent = JSON.stringify(log);
|
|
225
|
+
};
|
|
226
|
+
fs.writeFileSync(fpath, fcontent);
|
|
211
227
|
}
|
|
212
228
|
};
|
|
213
229
|
module.exports = TaskMgr;
|