multi-tasks 2.0.1 → 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.
Files changed (36) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +143 -138
  3. package/cmd.js +41 -41
  4. package/examples/example0/run-readme.js +87 -87
  5. package/examples/example0/run.js +52 -52
  6. package/examples/example1/RunnerConsumer.js +25 -25
  7. package/examples/example1/RunnerProducer.js +34 -34
  8. package/examples/example1/run.js +8 -8
  9. package/examples/example2/RunnerConsumer.js +39 -39
  10. package/examples/example2/RunnerProducer.js +34 -34
  11. package/examples/example2/run.js +22 -22
  12. package/index.js +3 -3
  13. package/monitors/cli.js +28 -28
  14. package/package.json +23 -23
  15. package/test/splitter.test.js +16 -16
  16. package/test/test_resume/step1_start_and_crash.js +56 -0
  17. package/test/test_resume/step2_resume.js +21 -0
  18. package/test/test_resume/test.sh +3 -0
  19. package/todo.txt +3 -3
  20. package/utils/asyncQueue.js +35 -31
  21. package/utils/backward-v1.js +10 -10
  22. package/utils/makedir.js +40 -50
  23. package/utils/randoms.js +21 -15
  24. package/utils/test/test_asyncqueue.js +115 -115
  25. package/utils/test_makedir.js +2 -2
  26. package/workers/Multithread.js +196 -176
  27. package/workers/TaskMgr.js +212 -181
  28. package/workers/WorkerMgr.js +30 -30
  29. package/workers/asMaster.js +122 -70
  30. package/workers/asWorker.js +13 -13
  31. package/workers/helper.js +21 -21
  32. package/workers/index.js +45 -7
  33. package/examples/example3-dynamicIncreasing/RunnerConsumer.js +0 -176
  34. package/examples/example3-dynamicIncreasing/RunnerProducer.js +0 -49
  35. package/examples/example3-dynamicIncreasing/run.js +0 -36
  36. package/examples/example3-dynamicIncreasing/util.js +0 -46
@@ -1,182 +1,213 @@
1
- const fs = require('fs');
2
- const pathutil = require('path');
3
- const makeDir = require('../utils/makedir');
4
- const randomsUtil = require('../utils/randoms');
5
-
6
- let taskCounter = 0;
7
-
8
- let taskFolder;
9
- let progressRootFolder;
10
- let resultsRootFolder;
11
-
12
- let taskFolderNew;
13
- let taskFolderRunning;
14
- let taskFolderFinished;;
15
- let taskFolderFailed;
16
-
17
- let taskFolderResult;
18
- let taskFolderResultFailed;
19
-
20
- let allSubTasks = {
21
- new:[],
22
- running:[],
23
- finished:[],
24
- finished_with_errors:[]
25
- };
26
-
27
- let main_config;
28
-
29
- const TaskMgr = {
30
- load:(config)=>{
31
- main_config = config;
32
- return TaskMgr;
33
- },
34
- initFolders:()=>{
35
- let {taskRootFolder, masterTaskId} = main_config;
36
- taskFolder = pathutil.resolve(taskRootFolder, masterTaskId);
37
- if(fs.existsSync(taskFolder)){
38
- let files = fs.readdirSync(taskFolder);
39
- if(files.length > 0){
40
- console.log('[FATAL] taskRootFolder already exist and not empty, delete it and try again: ', taskFolder);
41
- return process.exit(0);
42
- }
43
- };
44
- //let taskfolder = pathutil.parse(__filename).dir;
45
- //let taskFolder = pathutil.resolve(taskfolder, `./tasks/${masterTaskId}`);
46
- progressRootFolder = pathutil.resolve(taskFolder, './progress');
47
- resultsRootFolder = pathutil.resolve(taskFolder, './results');
48
-
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');
53
-
54
- taskFolderResult = pathutil.resolve(resultsRootFolder, './succ');
55
- taskFolderResultFailed = pathutil.resolve(resultsRootFolder, './errors');
56
- //let mainRptFolder = pathutil.resolve(taskfolder, './report');
57
-
58
- //makeDir.sync(mainRptFolder);
59
- makeDir.sync(taskFolderNew);
60
- makeDir.sync(taskFolderRunning);
61
- makeDir.sync(taskFolderFinished);
62
- makeDir.sync(taskFolderFailed);
63
- makeDir.sync(taskFolderResult);
64
- makeDir.sync(taskFolderResultFailed);
65
-
66
- main_config = {
67
- ...main_config,
68
- taskFolder,
69
- progressRootFolder,
70
- resultsRootFolder,
71
-
72
- taskFolderNew,
73
- taskFolderRunning,
74
- taskFolderFinished,
75
- taskFolderFailed,
76
- taskFolderResult,
77
- taskFolderResultFailed,
78
- };
79
-
80
- //for restart a failed task
81
- let main_config2 = JSON.parse(JSON.stringify(main_config));
82
- delete main_config2.tasks;//will load from folder 'new', so no need the early tasks data
83
- fs.writeFileSync(pathutil.resolve(taskFolder, 'task_config.json'), JSON.stringify(main_config2));
84
- return main_config;
85
- },
86
- createNewTask:(task)=>{
87
- const {masterTaskId, taskFolderNew} = main_config;
88
- const subid = randomsUtil.getDateTimeTxt() + Math.random();
89
-
90
- task.masterTaskId = masterTaskId;
91
- task.subid = `${masterTaskId}-${subid}`;
92
- let taskfilepath = pathutil.resolve(taskFolderNew, `./${task.subid}.task.json`);
93
- fs.writeFileSync(taskfilepath, JSON.stringify(task));
94
- },
95
- loadNewTasks:()=>{
96
- const {masterTaskId, taskFolderNew} = main_config;
97
- return new Promise((resolve)=>{
98
- console.log('get1')
99
- makeDir.getDirectFiles(taskFolderNew, (taskFiles)=>{
100
- taskFiles.forEach((filename)=>{
101
- let fpath = pathutil.resolve(taskFolderNew, filename);
102
- let fcontent;
103
- fcontent = fs.readFileSync(fpath, 'utf-8');
104
-
105
- if(fcontent){
106
- let task = JSON.parse(fcontent);
107
- allSubTasks.new.push(task);
108
- }
109
- });
110
- resolve()
111
- });
112
- });
113
- },
114
- updateNewTasks:()=>{
115
- let p;
116
- if(allSubTasks.new.length === 0){
117
- p = TaskMgr.loadNewTasks();//load again
118
- }else{
119
- p = Promise.resolve();
120
- }
121
- return p;
122
- },
123
- popNewTask:()=>{
124
- return new Promise((resolve)=>{
125
- let newtask = allSubTasks.new.shift();
126
- if(newtask){
127
- TaskMgr.mvTask(newtask.subid, 'new', 'running', (newPath)=>{
128
- resolve(newtask);
129
- });
130
- }else{
131
- resolve(null);
132
- }
133
- });
134
- },
135
- getTask:(type, id)=>{
136
- let result;
137
- let arr = allSubTasks[type];
138
- for(let i=0;i<arr.length;i++){
139
- let task = arr[i];
140
- if(task.subid === id){
141
- result = task;
142
- break;
143
- }
144
- }
145
- return result;
146
- },
147
- getTasks:(type)=>{
148
- return allSubTasks[type];
149
- },
150
- getTaskFiles:(type, callback)=>{
151
- let rootdir = main_config.progressRootFolder;
152
- let targetFolder = pathutil.resolve(rootdir, `./${type}`);
153
- console.log('get2')
154
- makeDir.getDirectFiles(targetFolder, (files)=>{
155
- callback(files);
156
- });
157
- },
158
- mvTask: (subid, from, to, callback)=> {
159
- //console.log('moooooov=======', subid, from, to)
160
- let {progressRootFolder} = main_config;
161
- let oldPath = pathutil.resolve(progressRootFolder, `./${from}/${subid}.task.json`);
162
- let newPath = pathutil.resolve(progressRootFolder, `./${to}/${subid}.task.json`);
163
-
164
- fs.rename(oldPath, newPath, (err) => {
165
- //if (err) throw err;
166
- callback(newPath);
167
- });
168
- },
169
- saveTaskResult:(subid, hasError, data)=>{
170
- let {taskFolderResult, taskFolderResultFailed} = main_config;
171
- let folder = hasError ? taskFolderResultFailed : taskFolderResult;
172
- let fpath = pathutil.resolve(folder, `${subid}.json`);
173
- let fcontent;
174
- if(typeof data === 'undefined') {
175
- fcontent = 'undefined';
176
- }else{
177
- fcontent = JSON.stringify(data);
178
- };
179
- fs.writeFileSync(fpath, fcontent);
180
- }
181
- };
1
+ const fs = require('fs');
2
+ const pathutil = require('path');
3
+ const makeDir = require('../utils/makedir');
4
+ const randomsUtil = require('../utils/randoms');
5
+
6
+ let taskCounter = 0;
7
+
8
+ let taskFolder;
9
+ let progressRootFolder;
10
+ let resultsRootFolder;
11
+
12
+ let taskFolderNew;
13
+ let taskFolderRunning;
14
+ let taskFolderFinished;;
15
+ let taskFolderFailed;
16
+
17
+ let taskFolderResult;
18
+ let taskFolderResultFailed;
19
+
20
+ let allSubTasks = {
21
+ new:[],
22
+ running:[],
23
+ finished:[],
24
+ finished_with_errors:[]
25
+ };
26
+
27
+ let main_config;
28
+
29
+ const TaskMgr = {
30
+ load:(config)=>{
31
+ main_config = config;
32
+ return TaskMgr;
33
+ },
34
+ initFolders:()=>{
35
+ let {taskRootFolder, masterTaskId} = main_config;
36
+ taskFolder = pathutil.resolve(taskRootFolder, masterTaskId);
37
+ if(fs.existsSync(taskFolder) && !(main_config.__resume || main_config.__restart)){
38
+ let files = fs.readdirSync(taskFolder);
39
+ if(files.length > 0){
40
+ console.log('[FATAL] taskRootFolder already exist and not empty, delete it and try again: ', taskFolder);
41
+ return process.exit(0);
42
+ }
43
+ };
44
+ //let taskfolder = pathutil.parse(__filename).dir;
45
+ //let taskFolder = pathutil.resolve(taskfolder, `./tasks/${masterTaskId}`);
46
+ progressRootFolder = pathutil.resolve(taskFolder, './progress');
47
+ resultsRootFolder = pathutil.resolve(taskFolder, './results');
48
+
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');
53
+
54
+ taskFolderResult = pathutil.resolve(resultsRootFolder, './succ');
55
+ taskFolderResultFailed = pathutil.resolve(resultsRootFolder, './errors');
56
+ //let mainRptFolder = pathutil.resolve(taskfolder, './report');
57
+
58
+ //makeDir.sync(mainRptFolder);
59
+ makeDir.sync(taskFolderNew);
60
+ makeDir.sync(taskFolderRunning);
61
+ makeDir.sync(taskFolderFinished);
62
+ makeDir.sync(taskFolderFailed);
63
+ makeDir.sync(taskFolderResult);
64
+ makeDir.sync(taskFolderResultFailed);
65
+
66
+ main_config = {
67
+ ...main_config,
68
+ taskFolder,
69
+ progressRootFolder,
70
+ resultsRootFolder,
71
+
72
+ taskFolderNew,
73
+ taskFolderRunning,
74
+ taskFolderFinished,
75
+ taskFolderFailed,
76
+ taskFolderResult,
77
+ taskFolderResultFailed,
78
+ };
79
+
80
+ //for restart a failed task
81
+ let main_config2 = JSON.parse(JSON.stringify(main_config));
82
+ delete main_config2.tasks;//will load from folder 'new', so no need the early tasks data
83
+ fs.writeFileSync(pathutil.resolve(taskFolder, 'task_config.json'), JSON.stringify(main_config2));
84
+ return main_config;
85
+ },
86
+ createNewTask:(task)=>{
87
+ const {masterTaskId, taskFolderNew} = main_config;
88
+ const subid = randomsUtil.get36Id();
89
+
90
+ task.masterTaskId = masterTaskId;
91
+ task.subid = `${masterTaskId}--${subid}`;
92
+ let taskfilepath = pathutil.resolve(taskFolderNew, `./${task.subid}.task.json`);
93
+ fs.writeFileSync(taskfilepath, JSON.stringify(task));
94
+ },
95
+ loadAllTasks:(loadtype)=>{
96
+ const {progressRootFolder} = main_config;
97
+ let load = (type)=>{
98
+ allSubTasks[type] = [];
99
+ return new Promise((resolve)=>{
100
+ let folder = pathutil.resolve(progressRootFolder, type);
101
+ makeDir.getDirectFiles(folder, (taskFiles)=>{
102
+ taskFiles.forEach((filename)=>{
103
+ let fpath = pathutil.resolve(folder, filename);
104
+ let fcontent;
105
+ try{
106
+ fcontent = fs.readFileSync(fpath, 'utf-8');
107
+ }catch(e){
108
+ console.log('[WARN]', `file not found`, fpath)
109
+ }
110
+ if(fcontent){
111
+ let task = JSON.parse(fcontent);
112
+ allSubTasks[type].push(task);
113
+ }
114
+ });
115
+ resolve(allSubTasks[type]);
116
+ });
117
+ });
118
+ };
119
+ let promises = [];
120
+ if(typeof loadtype === 'undefined'){
121
+ for(let type in allSubTasks){
122
+ promises.push(load(type));
123
+ }
124
+ }else{
125
+ promises.push(load(loadtype));
126
+ }
127
+ return Promise.all(promises);
128
+ },
129
+ loadNewTasks:()=>{
130
+ return TaskMgr.loadAllTasks('new');
131
+ },
132
+ updateNewTasks:()=>{
133
+ let p;
134
+ if(allSubTasks.new.length === 0){
135
+ p = TaskMgr.loadNewTasks();//load again
136
+ }else{
137
+ p = Promise.resolve();
138
+ }
139
+ return p;
140
+ },
141
+ popNewTask:()=>{
142
+ return new Promise((resolve)=>{
143
+ let newtask = allSubTasks.new.shift();
144
+ if(newtask){
145
+ TaskMgr.mvTask(newtask.subid, 'new', 'running', (newPath)=>{
146
+ resolve(newtask);
147
+ });
148
+ }else{
149
+ resolve(null);
150
+ }
151
+ });
152
+ },
153
+ getTask:(type, id)=>{
154
+ let result;
155
+ let arr = allSubTasks[type];
156
+ for(let i=0;i<arr.length;i++){
157
+ let task = arr[i];
158
+ if(task.subid === id){
159
+ result = task;
160
+ break;
161
+ }
162
+ }
163
+ return result;
164
+ },
165
+ getTasks:(type)=>{
166
+ return allSubTasks[type];
167
+ },
168
+ getTaskFiles:(type, callback)=>{
169
+ let rootdir = main_config.progressRootFolder;
170
+ let targetFolder = pathutil.resolve(rootdir, `./${type}`);
171
+ makeDir.getDirectFiles(targetFolder, (files)=>{
172
+ callback(files);
173
+ });
174
+ },
175
+ mvTaskPromise: (subid, from, to)=> {
176
+ return new Promise((resolve, reject)=>{
177
+ TaskMgr.mvTask(subid, from, to, (newPath, succ)=>{
178
+ succ ? resolve(newPath) : reject(newPath);
179
+ });
180
+ });
181
+ },
182
+ mvTask: (subid, from, to, callback)=> {
183
+ console.log('Move task:', subid, from, to, callback)
184
+ let {progressRootFolder} = main_config;
185
+ let oldPath = pathutil.resolve(progressRootFolder, `./${from}/${subid}.task.json`);
186
+ let newPath = pathutil.resolve(progressRootFolder, `./${to}/${subid}.task.json`);
187
+ try{
188
+ fs.rename(oldPath, newPath, (err) => {
189
+ if (err) {
190
+ callback(newPath, false);
191
+ }else{
192
+ callback(newPath, true);
193
+ }
194
+ });
195
+ }catch(e){
196
+ console.log(e);
197
+ callback(newPath, false);
198
+ }
199
+ },
200
+ saveTaskResult:(subid, hasError, data)=>{
201
+ let {taskFolderResult, taskFolderResultFailed} = main_config;
202
+ let folder = hasError ? taskFolderResultFailed : taskFolderResult;
203
+ let fpath = pathutil.resolve(folder, `${subid}.json`);
204
+ let fcontent;
205
+ if(typeof data === 'undefined') {
206
+ fcontent = 'undefined';
207
+ }else{
208
+ fcontent = JSON.stringify(data);
209
+ };
210
+ fs.writeFileSync(fpath, fcontent);
211
+ }
212
+ };
182
213
  module.exports = TaskMgr;
@@ -1,31 +1,31 @@
1
- const fs = require('fs');
2
- const pathutil = require('path');
3
- const makeDir = require('../utils/makedir');
4
-
5
- const BUSY = 1;
6
- const IDLE = 0;
7
-
8
- let workers = {};
9
- let status = {};
10
-
11
- const mgr = {
12
- addWorker:(worker)=>{
13
- let id = `${worker.id}`;
14
- if(workers[id] || status[id]){
15
- throw 'FATAL: duplicated worker!';
16
- }
17
- status[id] = {isBusy: true};
18
- console.log('add worker', worker.id);
19
- workers[id] = worker;
20
- },
21
- getWorker:(id)=>{
22
- return workers[`${id}`];
23
- },
24
- setBusy:(id, isBusy)=>{
25
-
26
- },
27
- isBusy:(id)=>{
28
-
29
- }
30
- };
1
+ const fs = require('fs');
2
+ const pathutil = require('path');
3
+ const makeDir = require('../utils/makedir');
4
+
5
+ const BUSY = 1;
6
+ const IDLE = 0;
7
+
8
+ let workers = {};
9
+ let status = {};
10
+
11
+ const mgr = {
12
+ addWorker:(worker)=>{
13
+ let id = `${worker.id}`;
14
+ if(workers[id] || status[id]){
15
+ throw 'FATAL: duplicated worker!';
16
+ }
17
+ status[id] = {isBusy: true};
18
+ console.log('add worker', worker.id);
19
+ workers[id] = worker;
20
+ },
21
+ getWorker:(id)=>{
22
+ return workers[`${id}`];
23
+ },
24
+ setBusy:(id, isBusy)=>{
25
+
26
+ },
27
+ isBusy:(id)=>{
28
+
29
+ }
30
+ };
31
31
  module.exports = mgr;
@@ -1,71 +1,123 @@
1
- var fs = require('fs');
2
- var pathutil = require('path');
3
- const numCPUs = require('os').cpus().length;
4
-
5
- let MSG_REQUEST_TASKID = 'request_taskid';
6
-
7
- const TaskMgr = require('./TaskMgr');
8
- const Multithread = require('./Multithread');
9
-
10
-
11
- const fmtDigit = (n)=>{
12
- return n > 9 ? "" + n: "0" + n;
13
- }
14
- const getDateTimeTxt = ()=>{
15
- let d=new Date();
16
- let YYYY=d.getFullYear()
17
- let MM=fmtDigit(d.getMonth()+1);
18
- let DD=fmtDigit(d.getDate());
19
- let HH=fmtDigit(d.getHours());
20
- let mm=fmtDigit(d.getMinutes());
21
- let ss=fmtDigit(d.getSeconds());
22
- return `${YYYY}-${MM}-${DD}_${HH}-${mm}-${ss}`;
23
- };
24
-
25
- const init = (config)=>{
26
- if(typeof config === 'undefined') config = {};
27
- if(!config.tasks){ throw 'Please provide tasks data!'; };
28
- if(!config.processTask){ throw 'Please provide processTask function!'; };
29
- if(!config.tasks){ throw 'Must assign initial tasks!'; };
30
-
31
- if(typeof config.numberOfWorkers === 'undefined') config.numberOfWorkers = numCPUs - 1;
32
-
33
- let {taskRootFolder, taskName} = config;
34
-
35
- if(taskName && !taskName.match(/[a-zA-Z0-9_-]/)){ throw 'Error: taskName can only contain letters and numbers'; }
36
- if(!taskName){ taskName = 'multitasks'; }
37
-
38
- let {round, pow, random} = Math;
39
- let dateTimeText = getDateTimeTxt();//moment().format('YYYY-MM-DD_HH-mm-ss');
40
- let randomNum = round((random() * pow(10,8)),8).toString(36);
41
- let masterTaskId = config.taskId ? config.taskId : `${taskName}${dateTimeText}--${randomNum}`;
42
-
43
- console.log(` masterTaskId===${masterTaskId}`);
44
-
45
- config.taskRootFolder = taskRootFolder;
46
- config.masterTaskId = masterTaskId;
47
-
48
-
49
- TaskMgr.load(config);
50
- config = TaskMgr.initFolders(config);
51
-
52
- config.tasks.forEach((task)=>{
53
- TaskMgr.createNewTask(task);
54
- });
55
-
56
- // let tasks = TaskMgr.getTasks('new')
57
- // let task = tasks.shift();
58
- // console.log(tasks)
59
- // TaskMgr.mvTask(task.subid, 'new', 'finished',()=>{})
60
-
61
- //to reload is for to reStart a collapsed task
62
- return new Promise((resolve)=>{
63
- TaskMgr.loadNewTasks().then(()=>{
64
- console.log('******start multi-thread')
65
- resolve(config);
66
- });
67
- });
68
- };
69
- module.exports = {
70
- init
1
+ var fs = require('fs');
2
+ var pathUtil = require('path');
3
+ const numCPUs = require('os').cpus().length;
4
+
5
+ let MSG_REQUEST_TASKID = 'request_taskid';
6
+
7
+ const TaskMgr = require('./TaskMgr');
8
+ const Multithread = require('./Multithread');
9
+
10
+
11
+ const fmtDigit = (n)=>{
12
+ return n > 9 ? "" + n: "0" + n;
13
+ }
14
+ const getDateTimeTxt = ()=>{
15
+ let d=new Date();
16
+ let YYYY=d.getFullYear()
17
+ let MM=fmtDigit(d.getMonth()+1);
18
+ let DD=fmtDigit(d.getDate());
19
+ let HH=fmtDigit(d.getHours());
20
+ let mm=fmtDigit(d.getMinutes());
21
+ let ss=fmtDigit(d.getSeconds());
22
+ return `${YYYY}-${MM}-${DD}_${HH}-${mm}-${ss}`;
23
+ };
24
+
25
+ const resume = (config)=>{
26
+ let {taskFolder} = config;
27
+ if(!taskFolder){
28
+ console.log('[ERROR]', 'method resume need param "taskFolder"')
29
+ throw ('[ERROR]', 'method resume need param "taskFolder"');
30
+ }
31
+ let pathinfo = pathUtil.parse(taskFolder);
32
+ let taskId = pathinfo.name;
33
+ let taskRootFolder = pathinfo.dir;
34
+
35
+ //load from config file
36
+ let task_config = JSON.parse(fs.readFileSync(pathUtil.resolve(taskFolder, 'task_config.json')));
37
+ config = {
38
+ ...config,
39
+ ...task_config
40
+ }
41
+
42
+ // config.taskId = taskId;
43
+ // config.taskRootFolder = taskRootFolder;
44
+ // config.masterTaskId = taskId;
45
+
46
+ TaskMgr.load(config);
47
+ config = TaskMgr.initFolders(config);
48
+
49
+ //console.log(config)
50
+
51
+ return new Promise((resolve)=>{
52
+
53
+ TaskMgr.getTaskFiles('running', (taskfiles)=>{
54
+ let promises = [];
55
+ taskfiles.forEach((fname)=>{
56
+ let subid = fname.replace(/\.task\.json$/, '');
57
+ promises.push(TaskMgr.mvTaskPromise(subid, 'running', 'new'));
58
+ });
59
+ Promise.all(promises).then(()=>{
60
+ TaskMgr.loadAllTasks().then((types)=>{
61
+ console.log('******resume multi-thread')
62
+ setTimeout(()=>{
63
+ resolve(config);
64
+ }, 1000);
65
+ });
66
+
67
+ }).catch((e)=>{
68
+ console.log('failed', e)
69
+ });
70
+ });
71
+ });
72
+
73
+
74
+ };
75
+
76
+ const init = (config)=>{
77
+ if(typeof config === 'undefined') config = {};
78
+ if(!config.tasks){ throw 'Please provide tasks data!'; };
79
+ if(!config.processTask){ throw 'Please provide processTask function!'; };
80
+ if(!config.tasks){ throw 'Must assign initial tasks!'; };
81
+
82
+ if(typeof config.numberOfWorkers === 'undefined') config.numberOfWorkers = numCPUs - 1;
83
+
84
+ let {taskRootFolder, taskName} = config;
85
+
86
+ if(taskName && !taskName.match(/[a-zA-Z0-9_-]/)){ throw 'Error: taskName can only contain letters and numbers'; }
87
+ if(!taskName){ taskName = 'multitasks'; }
88
+
89
+ let {round, pow, random} = Math;
90
+ let dateTimeText = getDateTimeTxt();//moment().format('YYYY-MM-DD_HH-mm-ss');
91
+ let randomNum = round((random() * pow(10,8)),8).toString(36);
92
+ let masterTaskId = config.taskId ? config.taskId : `${taskName}${dateTimeText}--${randomNum}`;
93
+
94
+ console.log(` masterTaskId===${masterTaskId}`);
95
+
96
+ config.taskRootFolder = taskRootFolder;
97
+ config.masterTaskId = masterTaskId;
98
+
99
+
100
+ TaskMgr.load(config);
101
+ config = TaskMgr.initFolders(config);
102
+
103
+ config.tasks.forEach((task)=>{
104
+ TaskMgr.createNewTask(task);
105
+ });
106
+
107
+ // let tasks = TaskMgr.getTasks('new')
108
+ // let task = tasks.shift();
109
+ // console.log(tasks)
110
+ // TaskMgr.mvTask(task.subid, 'new', 'finished',()=>{})
111
+
112
+ //to reload is for to reStart a collapsed task
113
+ return new Promise((resolve)=>{
114
+ TaskMgr.loadNewTasks().then(()=>{
115
+ console.log('******start multi-thread')
116
+ resolve(config);
117
+ });
118
+ });
119
+ };
120
+ module.exports = {
121
+ init,
122
+ resume
71
123
  };