multi-tasks 2.0.2 → 2.0.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.
- package/LICENSE +21 -21
- package/README.md +143 -140
- package/cmd.js +41 -41
- package/examples/example0/run-readme.js +87 -87
- package/examples/example0/run.js +52 -52
- package/examples/example1/RunnerConsumer.js +25 -25
- package/examples/example1/RunnerProducer.js +34 -34
- package/examples/example1/run.js +8 -8
- package/examples/example2/RunnerConsumer.js +39 -39
- package/examples/example2/RunnerProducer.js +34 -34
- package/examples/example2/run.js +22 -22
- package/index.js +3 -3
- package/monitors/cli.js +28 -28
- package/package.json +23 -23
- package/test/splitter.test.js +16 -16
- package/test/test_resume/step1_start_and_crash.js +56 -0
- package/test/test_resume/step2_resume.js +21 -0
- package/test/test_resume/test.sh +3 -0
- package/todo.txt +3 -3
- package/utils/asyncQueue.js +35 -35
- package/utils/backward-v1.js +10 -10
- package/utils/makedir.js +40 -54
- package/utils/randoms.js +21 -15
- package/utils/test/test_asyncqueue.js +115 -115
- package/utils/test_makedir.js +2 -2
- package/workers/Multithread.js +196 -197
- package/workers/TaskMgr.js +212 -185
- package/workers/WorkerMgr.js +30 -30
- package/workers/asMaster.js +122 -70
- package/workers/asWorker.js +13 -13
- package/workers/helper.js +21 -21
- package/workers/index.js +45 -42
package/examples/example0/run.js
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
let multiTasks = require('../../index').multiTasks;
|
|
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.start({
|
|
44
|
-
tasks: 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
|
-
}
|
|
1
|
+
let multiTasks = require('../../index').multiTasks;
|
|
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.start({
|
|
44
|
+
tasks: 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
53
|
});
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
let SuperConsumer = require('../../index').SuperConsumer;
|
|
2
|
-
|
|
3
|
-
class TestConsumer extends SuperConsumer {
|
|
4
|
-
|
|
5
|
-
processTask(actionData){
|
|
6
|
-
console.log(`processing data:`, actionData);
|
|
7
|
-
//you can also return a data instead of a promise object
|
|
8
|
-
let {index} = actionData;
|
|
9
|
-
if(index===3) throw 'exception';
|
|
10
|
-
if(index===4) return Promise.reject({err:'a test error'});
|
|
11
|
-
return new Promise((resolve) => {
|
|
12
|
-
setTimeout(() => {
|
|
13
|
-
let result = {
|
|
14
|
-
task:{
|
|
15
|
-
...actionData,
|
|
16
|
-
},
|
|
17
|
-
result: {
|
|
18
|
-
message: 'this is a result from a demo, random data=' + Math.random()
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
resolve(result);
|
|
22
|
-
}, 100);
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
let SuperConsumer = require('../../index').SuperConsumer;
|
|
2
|
+
|
|
3
|
+
class TestConsumer extends SuperConsumer {
|
|
4
|
+
|
|
5
|
+
processTask(actionData){
|
|
6
|
+
console.log(`processing data:`, actionData);
|
|
7
|
+
//you can also return a data instead of a promise object
|
|
8
|
+
let {index} = actionData;
|
|
9
|
+
if(index===3) throw 'exception';
|
|
10
|
+
if(index===4) return Promise.reject({err:'a test error'});
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
setTimeout(() => {
|
|
13
|
+
let result = {
|
|
14
|
+
task:{
|
|
15
|
+
...actionData,
|
|
16
|
+
},
|
|
17
|
+
result: {
|
|
18
|
+
message: 'this is a result from a demo, random data=' + Math.random()
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
resolve(result);
|
|
22
|
+
}, 100);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
26
|
module.exports = TestConsumer;
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
let SuperProducer = require('../../index').SuperProducer;
|
|
2
|
-
class TestProducer extends SuperProducer {
|
|
3
|
-
|
|
4
|
-
// constructor
|
|
5
|
-
constructor(taskname, parentfolder) {
|
|
6
|
-
super(taskname, parentfolder)
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
setTaskTrunkInfo(trunkInfo){
|
|
10
|
-
this.trunkInfo = trunkInfo;
|
|
11
|
-
}
|
|
12
|
-
getAllActions() {
|
|
13
|
-
/**
|
|
14
|
-
* Generate all your tasks in this method, return as an array;
|
|
15
|
-
* These data will be allocated to multiple threads (workers) for running;
|
|
16
|
-
* You can obtain each of the data and process it in the 'processTask' method of your consumer.
|
|
17
|
-
*
|
|
18
|
-
* **/
|
|
19
|
-
|
|
20
|
-
return new Promise((resolve, reject)=>{
|
|
21
|
-
let trunkInfo = this.trunkInfo;
|
|
22
|
-
let alltasks = []
|
|
23
|
-
for(let i=0;i<200;i++){
|
|
24
|
-
let task_props = {
|
|
25
|
-
index: i,
|
|
26
|
-
name: `task-${i}`,
|
|
27
|
-
description: `This prop is for a subtask`
|
|
28
|
-
};
|
|
29
|
-
alltasks.push(task_props);
|
|
30
|
-
}
|
|
31
|
-
resolve(alltasks);//return all your tasks as an array
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
}
|
|
1
|
+
let SuperProducer = require('../../index').SuperProducer;
|
|
2
|
+
class TestProducer extends SuperProducer {
|
|
3
|
+
|
|
4
|
+
// constructor
|
|
5
|
+
constructor(taskname, parentfolder) {
|
|
6
|
+
super(taskname, parentfolder)
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
setTaskTrunkInfo(trunkInfo){
|
|
10
|
+
this.trunkInfo = trunkInfo;
|
|
11
|
+
}
|
|
12
|
+
getAllActions() {
|
|
13
|
+
/**
|
|
14
|
+
* Generate all your tasks in this method, return as an array;
|
|
15
|
+
* These data will be allocated to multiple threads (workers) for running;
|
|
16
|
+
* You can obtain each of the data and process it in the 'processTask' method of your consumer.
|
|
17
|
+
*
|
|
18
|
+
* **/
|
|
19
|
+
|
|
20
|
+
return new Promise((resolve, reject)=>{
|
|
21
|
+
let trunkInfo = this.trunkInfo;
|
|
22
|
+
let alltasks = []
|
|
23
|
+
for(let i=0;i<200;i++){
|
|
24
|
+
let task_props = {
|
|
25
|
+
index: i,
|
|
26
|
+
name: `task-${i}`,
|
|
27
|
+
description: `This prop is for a subtask`
|
|
28
|
+
};
|
|
29
|
+
alltasks.push(task_props);
|
|
30
|
+
}
|
|
31
|
+
resolve(alltasks);//return all your tasks as an array
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
35
|
module.exports = TestProducer;
|
package/examples/example1/run.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
let RunnerProducer = require('./RunnerProducer');//You need to provide a Producer to return all subtasks, multi-tasks will automatically split them and execute them in a multi-threaded manner
|
|
2
|
-
let RunnerConsumer = require('./RunnerConsumer');//You need to provide a Consumer to process a certain sub-task and return the processed data
|
|
3
|
-
let master = require('../../index').master;
|
|
4
|
-
|
|
5
|
-
master.start(RunnerProducer, RunnerConsumer, {
|
|
6
|
-
multi_task_parent_folder: `C:/tmp-demo`,
|
|
7
|
-
quotaOfEachTask:2, //The number of tasks assigned to each worker
|
|
8
|
-
numberOfWorkers: 6
|
|
1
|
+
let RunnerProducer = require('./RunnerProducer');//You need to provide a Producer to return all subtasks, multi-tasks will automatically split them and execute them in a multi-threaded manner
|
|
2
|
+
let RunnerConsumer = require('./RunnerConsumer');//You need to provide a Consumer to process a certain sub-task and return the processed data
|
|
3
|
+
let master = require('../../index').master;
|
|
4
|
+
|
|
5
|
+
master.start(RunnerProducer, RunnerConsumer, {
|
|
6
|
+
multi_task_parent_folder: `C:/tmp-demo`,
|
|
7
|
+
quotaOfEachTask:2, //The number of tasks assigned to each worker
|
|
8
|
+
numberOfWorkers: 6
|
|
9
9
|
});
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
let SuperConsumer = require('../../index').SuperConsumer;
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
let _do = (mainTaskInfo, actions, callback)=>{
|
|
5
|
-
if(actions.length === 0) return callback({
|
|
6
|
-
data:'subtask finished, random data='+Math.random()
|
|
7
|
-
});
|
|
8
|
-
let actionData = actions.shift();
|
|
9
|
-
|
|
10
|
-
//start to write your process code here
|
|
11
|
-
|
|
12
|
-
console.log('actionData', actionData)
|
|
13
|
-
|
|
14
|
-
//end of your process code.
|
|
15
|
-
|
|
16
|
-
//trigger next task
|
|
17
|
-
_do(mainTaskInfo, actions, callback);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class TestConsumer extends SuperConsumer {
|
|
22
|
-
|
|
23
|
-
// constructor
|
|
24
|
-
constructor(taskname, parentfolder) {
|
|
25
|
-
super(taskname, parentfolder)
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
setTaskTrunkInfo(trunkInfo){
|
|
29
|
-
this.trunkInfo = trunkInfo;
|
|
30
|
-
}
|
|
31
|
-
run (mainTaskInfo, subTaskInfo, taskInfo, callback){
|
|
32
|
-
let actions = subTaskInfo.actions;
|
|
33
|
-
mainTaskInfo.defination = this.trunkInfo.defination;
|
|
34
|
-
_do(mainTaskInfo, actions, (result)=>{
|
|
35
|
-
callback(result)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
}
|
|
1
|
+
let SuperConsumer = require('../../index').SuperConsumer;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let _do = (mainTaskInfo, actions, callback)=>{
|
|
5
|
+
if(actions.length === 0) return callback({
|
|
6
|
+
data:'subtask finished, random data='+Math.random()
|
|
7
|
+
});
|
|
8
|
+
let actionData = actions.shift();
|
|
9
|
+
|
|
10
|
+
//start to write your process code here
|
|
11
|
+
|
|
12
|
+
console.log('actionData', actionData)
|
|
13
|
+
|
|
14
|
+
//end of your process code.
|
|
15
|
+
|
|
16
|
+
//trigger next task
|
|
17
|
+
_do(mainTaskInfo, actions, callback);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestConsumer extends SuperConsumer {
|
|
22
|
+
|
|
23
|
+
// constructor
|
|
24
|
+
constructor(taskname, parentfolder) {
|
|
25
|
+
super(taskname, parentfolder)
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
setTaskTrunkInfo(trunkInfo){
|
|
29
|
+
this.trunkInfo = trunkInfo;
|
|
30
|
+
}
|
|
31
|
+
run (mainTaskInfo, subTaskInfo, taskInfo, callback){
|
|
32
|
+
let actions = subTaskInfo.actions;
|
|
33
|
+
mainTaskInfo.defination = this.trunkInfo.defination;
|
|
34
|
+
_do(mainTaskInfo, actions, (result)=>{
|
|
35
|
+
callback(result)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
40
|
module.exports = TestConsumer;
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
let SuperProducer = require('../../index').SuperProducer;
|
|
2
|
-
class TestProducer extends SuperProducer {
|
|
3
|
-
|
|
4
|
-
// constructor
|
|
5
|
-
constructor(taskname, parentfolder) {
|
|
6
|
-
super(taskname, parentfolder)
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
setTaskTrunkInfo(trunkInfo){
|
|
10
|
-
this.trunkInfo = trunkInfo;
|
|
11
|
-
}
|
|
12
|
-
getAllActions() {
|
|
13
|
-
/**
|
|
14
|
-
* Generate all your tasks in this method, return as an array;
|
|
15
|
-
* These data will be allocated to multiple threads (workers) for running;
|
|
16
|
-
* You can obtain each of the data and process it in the 'processTask' method of your consumer.
|
|
17
|
-
*
|
|
18
|
-
* **/
|
|
19
|
-
|
|
20
|
-
return new Promise((resolve, reject)=>{
|
|
21
|
-
let trunkInfo = this.trunkInfo;
|
|
22
|
-
let alltasks = []
|
|
23
|
-
for(let i=0;i<200;i++){
|
|
24
|
-
let task_props = {
|
|
25
|
-
index: i,
|
|
26
|
-
name: `task-${i}`,
|
|
27
|
-
description: `This prop is for a subtask`
|
|
28
|
-
};
|
|
29
|
-
alltasks.push(task_props);
|
|
30
|
-
}
|
|
31
|
-
resolve(alltasks);//return all your tasks as an array
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
}
|
|
1
|
+
let SuperProducer = require('../../index').SuperProducer;
|
|
2
|
+
class TestProducer extends SuperProducer {
|
|
3
|
+
|
|
4
|
+
// constructor
|
|
5
|
+
constructor(taskname, parentfolder) {
|
|
6
|
+
super(taskname, parentfolder)
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
setTaskTrunkInfo(trunkInfo){
|
|
10
|
+
this.trunkInfo = trunkInfo;
|
|
11
|
+
}
|
|
12
|
+
getAllActions() {
|
|
13
|
+
/**
|
|
14
|
+
* Generate all your tasks in this method, return as an array;
|
|
15
|
+
* These data will be allocated to multiple threads (workers) for running;
|
|
16
|
+
* You can obtain each of the data and process it in the 'processTask' method of your consumer.
|
|
17
|
+
*
|
|
18
|
+
* **/
|
|
19
|
+
|
|
20
|
+
return new Promise((resolve, reject)=>{
|
|
21
|
+
let trunkInfo = this.trunkInfo;
|
|
22
|
+
let alltasks = []
|
|
23
|
+
for(let i=0;i<200;i++){
|
|
24
|
+
let task_props = {
|
|
25
|
+
index: i,
|
|
26
|
+
name: `task-${i}`,
|
|
27
|
+
description: `This prop is for a subtask`
|
|
28
|
+
};
|
|
29
|
+
alltasks.push(task_props);
|
|
30
|
+
}
|
|
31
|
+
resolve(alltasks);//return all your tasks as an array
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
35
|
module.exports = TestProducer;
|
package/examples/example2/run.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
let RunnerProducer = require('./RunnerProducer');//switch to require from node_modules in your project
|
|
2
|
-
let RunnerConsumer = require('./RunnerConsumer');//switch to require from node_modules in your project
|
|
3
|
-
|
|
4
|
-
let taskId = Math.random()+'';
|
|
5
|
-
let multi_task_parent_folder = `C:/tmp-demo`;
|
|
6
|
-
|
|
7
|
-
let producer = new RunnerProducer(`workers_of_${taskId}`, multi_task_parent_folder)
|
|
8
|
-
let consumer = new RunnerConsumer();
|
|
9
|
-
let master = require('../../index').master;
|
|
10
|
-
|
|
11
|
-
console.log(producer.getTaskName())
|
|
12
|
-
//return;
|
|
13
|
-
|
|
14
|
-
let taskConfig = {
|
|
15
|
-
multi_task_parent_folder
|
|
16
|
-
}
|
|
17
|
-
//console.log(resp)
|
|
18
|
-
producer.setTaskTrunkInfo(taskConfig);
|
|
19
|
-
consumer.setTaskTrunkInfo(taskConfig)
|
|
20
|
-
master.run(producer, consumer, {
|
|
21
|
-
quotaOfEachTask:2,
|
|
22
|
-
numberOfWorkers: 6
|
|
1
|
+
let RunnerProducer = require('./RunnerProducer');//switch to require from node_modules in your project
|
|
2
|
+
let RunnerConsumer = require('./RunnerConsumer');//switch to require from node_modules in your project
|
|
3
|
+
|
|
4
|
+
let taskId = Math.random()+'';
|
|
5
|
+
let multi_task_parent_folder = `C:/tmp-demo`;
|
|
6
|
+
|
|
7
|
+
let producer = new RunnerProducer(`workers_of_${taskId}`, multi_task_parent_folder)
|
|
8
|
+
let consumer = new RunnerConsumer();
|
|
9
|
+
let master = require('../../index').master;
|
|
10
|
+
|
|
11
|
+
console.log(producer.getTaskName())
|
|
12
|
+
//return;
|
|
13
|
+
|
|
14
|
+
let taskConfig = {
|
|
15
|
+
multi_task_parent_folder
|
|
16
|
+
}
|
|
17
|
+
//console.log(resp)
|
|
18
|
+
producer.setTaskTrunkInfo(taskConfig);
|
|
19
|
+
consumer.setTaskTrunkInfo(taskConfig)
|
|
20
|
+
master.run(producer, consumer, {
|
|
21
|
+
quotaOfEachTask:2,
|
|
22
|
+
numberOfWorkers: 6
|
|
23
23
|
});
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const multiTasks = require('./workers');
|
|
2
|
-
module.exports = {
|
|
3
|
-
multiTasks
|
|
1
|
+
const multiTasks = require('./workers');
|
|
2
|
+
module.exports = {
|
|
3
|
+
multiTasks
|
|
4
4
|
}
|
package/monitors/cli.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
const cliProgress = require('cli-progress');
|
|
2
|
-
|
|
3
|
-
// create new container
|
|
4
|
-
const multibar = new cliProgress.MultiBar({
|
|
5
|
-
clearOnComplete: false,
|
|
6
|
-
hideCursor: true,
|
|
7
|
-
format: ' {bar} | {filename} | {value}/{total}',
|
|
8
|
-
}, cliProgress.Presets.shades_grey);
|
|
9
|
-
|
|
10
|
-
// add bars
|
|
11
|
-
const b1 = multibar.create(200, 0);
|
|
12
|
-
const b2 = multibar.create(1000, 0);
|
|
13
|
-
|
|
14
|
-
// control bars
|
|
15
|
-
b1.increment();
|
|
16
|
-
b2.update(20, {filename: "test1.txt"});
|
|
17
|
-
b1.update(20, {filename: "helloworld.txt"});
|
|
18
|
-
|
|
19
|
-
b2.setTotal(2000);
|
|
20
|
-
let v = 200;
|
|
21
|
-
setInterval(()=>{
|
|
22
|
-
v=v+20
|
|
23
|
-
b2.update(v, {filename: "2222.txt"});
|
|
24
|
-
|
|
25
|
-
// stop all bars
|
|
26
|
-
|
|
27
|
-
//multibar.stop();
|
|
28
|
-
}, 300)
|
|
1
|
+
const cliProgress = require('cli-progress');
|
|
2
|
+
|
|
3
|
+
// create new container
|
|
4
|
+
const multibar = new cliProgress.MultiBar({
|
|
5
|
+
clearOnComplete: false,
|
|
6
|
+
hideCursor: true,
|
|
7
|
+
format: ' {bar} | {filename} | {value}/{total}',
|
|
8
|
+
}, cliProgress.Presets.shades_grey);
|
|
9
|
+
|
|
10
|
+
// add bars
|
|
11
|
+
const b1 = multibar.create(200, 0);
|
|
12
|
+
const b2 = multibar.create(1000, 0);
|
|
13
|
+
|
|
14
|
+
// control bars
|
|
15
|
+
b1.increment();
|
|
16
|
+
b2.update(20, {filename: "test1.txt"});
|
|
17
|
+
b1.update(20, {filename: "helloworld.txt"});
|
|
18
|
+
|
|
19
|
+
b2.setTotal(2000);
|
|
20
|
+
let v = 200;
|
|
21
|
+
setInterval(()=>{
|
|
22
|
+
v=v+20
|
|
23
|
+
b2.update(v, {filename: "2222.txt"});
|
|
24
|
+
|
|
25
|
+
// stop all bars
|
|
26
|
+
|
|
27
|
+
//multibar.stop();
|
|
28
|
+
}, 300)
|
package/package.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "multi-tasks",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"directories": {
|
|
7
|
-
"example": "example"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "jest"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"multitask",
|
|
14
|
-
"worker",
|
|
15
|
-
"multithread"
|
|
16
|
-
],
|
|
17
|
-
"author": "zhanglei923@gmail.com",
|
|
18
|
-
"license": "MIT",
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"cli-progress": "^3.12.0",
|
|
21
|
-
"jest": "^29.7.0"
|
|
22
|
-
}
|
|
23
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "multi-tasks",
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"directories": {
|
|
7
|
+
"example": "example"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "jest"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"multitask",
|
|
14
|
+
"worker",
|
|
15
|
+
"multithread"
|
|
16
|
+
],
|
|
17
|
+
"author": "zhanglei923@gmail.com",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"cli-progress": "^3.12.0",
|
|
21
|
+
"jest": "^29.7.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/test/splitter.test.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
let splitter = require('../workers/taskSplitter');
|
|
2
|
-
|
|
3
|
-
let createArray = (len)=>{
|
|
4
|
-
let alltasks = []
|
|
5
|
-
for(let i=0;i<len;i++){
|
|
6
|
-
alltasks.push(i)
|
|
7
|
-
}
|
|
8
|
-
return alltasks;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
test('test taskSplitter', async () => {
|
|
12
|
-
|
|
13
|
-
expect(splitter.split(createArray(3), 5).length).toBe(1);
|
|
14
|
-
expect(splitter.split(createArray(16), 5).length).toBe(4);
|
|
15
|
-
expect(splitter.split(createArray(101), 1).length).toBe(101);
|
|
16
|
-
expect(splitter.split(createArray(101), 33).length).toBe(4);
|
|
1
|
+
let splitter = require('../workers/taskSplitter');
|
|
2
|
+
|
|
3
|
+
let createArray = (len)=>{
|
|
4
|
+
let alltasks = []
|
|
5
|
+
for(let i=0;i<len;i++){
|
|
6
|
+
alltasks.push(i)
|
|
7
|
+
}
|
|
8
|
+
return alltasks;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
test('test taskSplitter', async () => {
|
|
12
|
+
|
|
13
|
+
expect(splitter.split(createArray(3), 5).length).toBe(1);
|
|
14
|
+
expect(splitter.split(createArray(16), 5).length).toBe(4);
|
|
15
|
+
expect(splitter.split(createArray(101), 1).length).toBe(101);
|
|
16
|
+
expect(splitter.split(createArray(101), 33).length).toBe(4);
|
|
17
17
|
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
let multiTasks = require('../../index').multiTasks;
|
|
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.start({
|
|
44
|
+
tasks: alltasks,
|
|
45
|
+
processTask,
|
|
46
|
+
taskRootFolder: `./tmp`, //a directory to store progress and results files, you can check the progress here
|
|
47
|
+
taskId: 'test_resume',
|
|
48
|
+
numberOfWorkers: 3, //Assign how many workers are working in parallel
|
|
49
|
+
//autoCloseAfterCompletion: true,
|
|
50
|
+
shouldTerminate:(info)=>{
|
|
51
|
+
if(info.taskCount > 30) return true;
|
|
52
|
+
},
|
|
53
|
+
onFinish: (report)=>{
|
|
54
|
+
console.log('finish callback', report);
|
|
55
|
+
}
|
|
56
|
+
});
|