multi-tasks 2.1.0 → 2.1.1
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 +1 -0
- package/examples/example0/run.js +6 -0
- package/package.json +1 -1
- package/workers/Multithread.js +54 -44
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ let processTask = (task, helper)=>{
|
|
|
111
111
|
|
|
112
112
|
Changelog:
|
|
113
113
|
|
|
114
|
+
- 2.1.1 Fixbug: recreate a new one when a worker collapsed unexpectedly.
|
|
114
115
|
- 2.1.0 Add a new output directory "log" where you can view the process time of each subtask
|
|
115
116
|
- 2.0.9 Update readme examples
|
|
116
117
|
- 2.0.8 Update readme examples
|
package/examples/example0/run.js
CHANGED
|
@@ -25,6 +25,12 @@ let processTask = (task, helper)=>{
|
|
|
25
25
|
if(taskCount===5) aaa = bbb;
|
|
26
26
|
|
|
27
27
|
if(taskCount===6) return 'a result which is not a promise'; //Return a non-promise result is also OK
|
|
28
|
+
|
|
29
|
+
if(taskCount===7) {return new Promise((resolve, reject)=>{//async exception
|
|
30
|
+
setTimeout(()=>{
|
|
31
|
+
a=beforeAll;
|
|
32
|
+
}, 10 * Math.random())
|
|
33
|
+
});}
|
|
28
34
|
|
|
29
35
|
//by default, you should return a promise, all returned data can be found in the results/succ folder
|
|
30
36
|
return new Promise((resolve, reject)=>{
|
package/package.json
CHANGED
package/workers/Multithread.js
CHANGED
|
@@ -61,58 +61,68 @@ const start = (config)=>{
|
|
|
61
61
|
const AsyncQueue = require(`../utils/asyncQueue`);
|
|
62
62
|
const queue = new AsyncQueue();
|
|
63
63
|
|
|
64
|
+
let initWorker = (worker)=>{
|
|
65
|
+
WorkerMgr.addWorker(worker);
|
|
66
|
+
worker.on('message', function(message) {
|
|
67
|
+
if(message === MSG_REQUEST_NEW_TASK){
|
|
68
|
+
queue.enqueue(async ()=>{
|
|
69
|
+
return TaskMgr.updateNewTasks();
|
|
70
|
+
});//use queue to make sure no I/O conflict
|
|
71
|
+
queue.enqueue(async () => {
|
|
72
|
+
return TaskMgr.popNewTask().then((subTask)=>{
|
|
73
|
+
if(!subTask){
|
|
74
|
+
//no tasks left
|
|
75
|
+
console.log('[Master]: no tasks left!');
|
|
76
|
+
//console.log('workers', cluster.workers);
|
|
77
|
+
if(config.autoCloseAfterCompletion){
|
|
78
|
+
killWorker(worker);
|
|
79
|
+
}else{//waiting for new tasks
|
|
80
|
+
worker.send(MSG_NO_TASK_FOUND,()=>{}, {
|
|
81
|
+
keepOpen: (typeof config.keepOpen === 'undefined') ? false : config.keepOpen
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}else{
|
|
85
|
+
let terminateData = {taskCount,subTask,config, id: worker.id};
|
|
86
|
+
if(USER_CONFIG.shouldTerminate && USER_CONFIG.shouldTerminate(terminateData)===true) {
|
|
87
|
+
killAllWorkers();
|
|
88
|
+
return process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
//send new tasks to the worker
|
|
91
|
+
worker.send({
|
|
92
|
+
taskCount,
|
|
93
|
+
startTimestamp: new Date()*1,
|
|
94
|
+
config,
|
|
95
|
+
subTask
|
|
96
|
+
},()=>{}, {
|
|
97
|
+
keepOpen: (typeof config.keepOpen === 'undefined') ? false : config.keepOpen
|
|
98
|
+
});
|
|
99
|
+
taskCount++;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}else
|
|
104
|
+
if(message.MSG_SET_GLOBAL_PARAMS){
|
|
105
|
+
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxx', message)
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
64
110
|
let initPromise = config.__resume ? asMaster.resume(config) : asMaster.init(config);
|
|
65
111
|
initPromise.then((updated_config)=>{
|
|
66
112
|
console.log(` new tasks=${TaskMgr.getTasks('new').length}`);
|
|
67
113
|
config = updated_config;
|
|
68
114
|
for (let i = 0; i < numOfWorkers; i++) {
|
|
69
115
|
let worker = cluster.fork();
|
|
70
|
-
|
|
71
|
-
worker.on('message', function(message) {
|
|
72
|
-
if(message === MSG_REQUEST_NEW_TASK){
|
|
73
|
-
queue.enqueue(async ()=>{
|
|
74
|
-
return TaskMgr.updateNewTasks();
|
|
75
|
-
});//use queue to make sure no I/O conflict
|
|
76
|
-
queue.enqueue(async () => {
|
|
77
|
-
return TaskMgr.popNewTask().then((subTask)=>{
|
|
78
|
-
if(!subTask){
|
|
79
|
-
//no tasks left
|
|
80
|
-
console.log('[Master]: no tasks left!');
|
|
81
|
-
//console.log('workers', cluster.workers);
|
|
82
|
-
if(config.autoCloseAfterCompletion){
|
|
83
|
-
killWorker(worker);
|
|
84
|
-
}else{//waiting for new tasks
|
|
85
|
-
worker.send(MSG_NO_TASK_FOUND,()=>{}, {
|
|
86
|
-
keepOpen: (typeof config.keepOpen === 'undefined') ? false : config.keepOpen
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}else{
|
|
90
|
-
let terminateData = {taskCount,subTask,config, id: worker.id};
|
|
91
|
-
if(USER_CONFIG.shouldTerminate && USER_CONFIG.shouldTerminate(terminateData)===true) {
|
|
92
|
-
killAllWorkers();
|
|
93
|
-
return process.exit(0);
|
|
94
|
-
}
|
|
95
|
-
//send new tasks to the worker
|
|
96
|
-
worker.send({
|
|
97
|
-
taskCount,
|
|
98
|
-
startTimestamp: new Date()*1,
|
|
99
|
-
config,
|
|
100
|
-
subTask
|
|
101
|
-
},()=>{}, {
|
|
102
|
-
keepOpen: (typeof config.keepOpen === 'undefined') ? false : config.keepOpen
|
|
103
|
-
});
|
|
104
|
-
taskCount++;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
}else
|
|
109
|
-
if(message.MSG_SET_GLOBAL_PARAMS){
|
|
110
|
-
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxx', message)
|
|
111
|
-
}
|
|
112
|
-
});
|
|
116
|
+
initWorker(worker);
|
|
113
117
|
}
|
|
114
118
|
});
|
|
115
|
-
cluster.on('exit', (worker, code, signal) => {
|
|
119
|
+
cluster.on('exit', (worker, code, signal) => {
|
|
120
|
+
if (code !== 0 && !worker.exitedAfterDisconnect) {
|
|
121
|
+
console.log('Worker died unexpectedly starting a new one...');
|
|
122
|
+
let worker = cluster.fork();
|
|
123
|
+
initWorker(worker);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
116
126
|
let allkilled = true;
|
|
117
127
|
for (const worker of Object.values(cluster.workers)) {
|
|
118
128
|
allkilled = allkilled && worker.killed;
|