multi-tasks 3.2.3 → 3.4.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.
@@ -1,27 +1,18 @@
1
- let workers = {};
2
- let status = {};
3
-
4
- const runLog = require('../utils/runLog');
5
-
6
- const mgr = {
7
- addWorker:(worker)=>{
8
- let id = `${worker.id}`;
9
- if(workers[id] || status[id]){
10
- throw new Error('FATAL: duplicated worker!');
11
- }
12
- status[id] = {isBusy: true};
13
- runLog.write('add worker', worker.id);
14
- workers[id] = worker;
15
- },
16
- getWorker:(id)=>{
17
- return workers[`${id}`];
18
- },
19
- setBusy:(id, isBusy)=>{
20
- status[`${id}`] = {isBusy: isBusy};
21
- },
22
- isBusy:(id)=>{
23
- let s = status[`${id}`];
24
- return s ? s.isBusy : false;
25
- }
26
- };
27
- module.exports = mgr;
1
+ let workers = {};
2
+
3
+ const runLog = require('../utils/runLog');
4
+
5
+ const mgr = {
6
+ addWorker:(worker)=>{
7
+ let id = `${worker.id}`;
8
+ if(workers[id]){
9
+ throw new Error('FATAL: duplicated worker!');
10
+ }
11
+ runLog.write('add worker', worker.id);
12
+ workers[id] = worker;
13
+ },
14
+ removeWorker:(id)=>{//worker 退出(含崩溃补员)时清引用: map 只增不减会累积死 worker
15
+ delete workers[`${id}`];
16
+ }
17
+ };
18
+ module.exports = mgr;
@@ -1,101 +1,102 @@
1
- var fs = require('fs');
2
- var pathUtil = require('path');
3
-
4
- const TaskMgr = require('./TaskMgr');
5
- const randomsUtil = require('../utils/randoms');
6
- const { resolveNumberOfWorkers } = require('../utils/resolveWorkers');
7
-
8
- const resume = (config)=>{
9
- config.__resume = true;
10
- let {taskRootFolder, taskId} = config;
11
- let taskFolder = pathUtil.resolve(taskRootFolder, taskId);
12
-
13
- //load from config file: 旧快照作底(兼作任务目录合法性校验, 不存在抛 ENOENT),
14
- //本次调用传入的配置覆盖同名字段——快照只补未传入的字段
15
- let task_config = JSON.parse(fs.readFileSync(pathUtil.resolve(taskFolder, 'task_config.json')));
16
- Object.keys(task_config).forEach((key)=>{
17
- if(key.startsWith('__')) delete task_config[key];//读侧剔除一次性标记, 兼容 <=3.1.3 旧快照
18
- });
19
- config = {
20
- ...task_config,
21
- ...config
22
- };
23
- config.masterTaskId = taskId;
24
-
25
- TaskMgr.load(config);
26
- config = TaskMgr.initFolders(config);
27
-
28
- return new Promise((resolve, reject)=>{
29
-
30
- TaskMgr.getTaskFiles('running', (taskfiles)=>{
31
- TaskMgr.getTaskFiles('finished_with_errors', (errfiles)=>{
32
- let promises = [];
33
- taskfiles.forEach((fname)=>{
34
- let subid = fname.replace(/\.task\.json$/, '');
35
- promises.push(TaskMgr.mvTaskPromise(subid, 'running', 'new'));
36
- });
37
- if(config.__retryFails){
38
- errfiles.forEach((fname)=>{
39
- let subid = fname.replace(/\.task\.json$/, '');
40
- promises.push(TaskMgr.mvTaskPromise(subid, 'finished_with_errors', 'new').then(()=>{
41
- TaskMgr.resetTaskRetry(subid);//retry_fails 重跑失败任务时重置重试计数(resume 不重置)
42
- }));
43
- });
44
- };
45
- Promise.all(promises).then(()=>{
46
- TaskMgr.loadAllTasks().then((types)=>{
47
- console.log('******resume multi-thread')
48
- setTimeout(()=>{
49
- resolve(config);
50
- }, 1000);
51
- });
52
-
53
- }).catch((e)=>{
54
- reject(e);
55
- });
56
- });
57
- });
58
- });
59
-
60
-
61
- };
62
-
63
- const init = (config)=>{
64
- if(!config) config = {};
65
- if(!config.initialTasks){ throw new Error('Please provide initialTasks data!'); };
66
- if(!config.processTask){ throw new Error('Please provide processTask function!'); };
67
-
68
- config.numberOfWorkers = resolveNumberOfWorkers(config.numberOfWorkers);//支持百分比字符串, 非法值在此抛错(fail fast, 不建任务目录)
69
-
70
- let {taskRootFolder, taskName} = config;
71
-
72
- if(taskName && !taskName.match(/^[a-zA-Z0-9_-]+$/)){ throw new Error('Error: taskName can only contain letters and numbers'); }
73
- if(!taskName){ taskName = 'multitasks'; }
74
-
75
- let {round, pow, random} = Math;
76
- let dateTimeText = randomsUtil.getDateTimeTxt();
77
- let randomNum = round((random() * pow(10,8)),8).toString(36);
78
- let masterTaskId = config.taskId ? config.taskId : `${taskName}${dateTimeText}--${randomNum}`;
79
-
80
- config.taskRootFolder = taskRootFolder;
81
- config.masterTaskId = masterTaskId;
82
-
83
-
84
- TaskMgr.load(config);
85
- config = TaskMgr.initFolders(config);
86
-
87
- config.initialTasks.forEach((task)=>{
88
- TaskMgr.createNewTask(task);
89
- });
90
-
91
- //to reload is for to reStart a collapsed task
92
- return new Promise((resolve)=>{
93
- TaskMgr.loadNewTasks().then(()=>{
94
- resolve(config);
95
- });
96
- });
97
- };
98
- module.exports = {
99
- init,
100
- resume
1
+ var fs = require('fs');
2
+ var pathUtil = require('path');
3
+
4
+ const TaskMgr = require('./TaskMgr');
5
+ const randomsUtil = require('../utils/randoms');
6
+ const { resolveNumberOfWorkers } = require('../utils/resolveWorkers');
7
+
8
+ const resume = (config)=>{
9
+ config.__resume = true;
10
+ let {taskRootFolder, taskId} = config;
11
+ let taskFolder = pathUtil.resolve(taskRootFolder, taskId);
12
+
13
+ //load from config file: 旧快照作底(兼作任务目录合法性校验, 不存在抛 ENOENT),
14
+ //本次调用传入的配置覆盖同名字段——快照只补未传入的字段
15
+ let task_config = JSON.parse(fs.readFileSync(pathUtil.resolve(taskFolder, 'task_config.json')));
16
+ Object.keys(task_config).forEach((key)=>{
17
+ if(key.startsWith('__')) delete task_config[key];//读侧剔除一次性标记, 兼容 <=3.1.3 旧快照
18
+ });
19
+ config = {
20
+ ...task_config,
21
+ ...config
22
+ };
23
+ config.masterTaskId = taskId;
24
+
25
+ TaskMgr.load(config);
26
+ config = TaskMgr.initFolders(config);
27
+
28
+ return new Promise((resolve, reject)=>{
29
+
30
+ TaskMgr.getTaskFiles('running', (taskfiles)=>{
31
+ TaskMgr.getTaskFiles('finished_with_errors', (errfiles)=>{
32
+ let promises = [];
33
+ taskfiles.forEach((fname)=>{
34
+ let subid = fname.replace(/\.task\.json$/, '');
35
+ promises.push(TaskMgr.mvTaskPromise(subid, 'running', 'new'));
36
+ });
37
+ if(config.__retryFails){
38
+ errfiles.forEach((fname)=>{
39
+ let subid = fname.replace(/\.task\.json$/, '');
40
+ promises.push(TaskMgr.mvTaskPromise(subid, 'finished_with_errors', 'new').then(()=>{
41
+ TaskMgr.resetTaskRetry(subid);//retry_fails 重跑失败任务时重置重试计数(resume 不重置)
42
+ TaskMgr.deleteUserMessage(subid);//重跑即新一轮: 清掉该任务在 .sys/user_messages 的遗留消息
43
+ }));
44
+ });
45
+ };
46
+ Promise.all(promises).then(()=>{
47
+ TaskMgr.loadAllTasks().then((types)=>{
48
+ console.log('******resume multi-thread')
49
+ setTimeout(()=>{
50
+ resolve(config);
51
+ }, 1000);
52
+ });
53
+
54
+ }).catch((e)=>{
55
+ reject(e);
56
+ });
57
+ });
58
+ });
59
+ });
60
+
61
+
62
+ };
63
+
64
+ const init = (config)=>{
65
+ if(!config) config = {};
66
+ if(!config.initialTasks){ throw new Error('Please provide initialTasks data!'); };
67
+ if(!config.processTask){ throw new Error('Please provide processTask function!'); };
68
+
69
+ config.numberOfWorkers = resolveNumberOfWorkers(config.numberOfWorkers);//支持百分比字符串, 非法值在此抛错(fail fast, 不建任务目录)
70
+
71
+ let {taskRootFolder, taskName} = config;
72
+
73
+ if(taskName && !taskName.match(/^[a-zA-Z0-9_-]+$/)){ throw new Error('Error: taskName can only contain letters and numbers'); }
74
+ if(!taskName){ taskName = 'multitasks'; }
75
+
76
+ let {round, pow, random} = Math;
77
+ let dateTimeText = randomsUtil.getDateTimeTxt();
78
+ let randomNum = round((random() * pow(10,8)),8).toString(36);
79
+ let masterTaskId = config.taskId ? config.taskId : `${taskName}${dateTimeText}--${randomNum}`;
80
+
81
+ config.taskRootFolder = taskRootFolder;
82
+ config.masterTaskId = masterTaskId;
83
+
84
+
85
+ TaskMgr.load(config);
86
+ config = TaskMgr.initFolders(config);
87
+
88
+ config.initialTasks.forEach((task)=>{
89
+ TaskMgr.createNewTask(task);
90
+ });
91
+
92
+ //to reload is for to reStart a collapsed task
93
+ return new Promise((resolve)=>{
94
+ TaskMgr.loadNewTasks().then(()=>{
95
+ resolve(config);
96
+ });
97
+ });
98
+ };
99
+ module.exports = {
100
+ init,
101
+ resume
101
102
  };