multi-tasks 1.0.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.
@@ -0,0 +1,32 @@
1
+ let SuperConsumer = require('multi-task').SuperConsumer;
2
+
3
+
4
+ let _do = (mainTaskInfo, actions, callback)=>{
5
+ if(actions.length === 0) return callback({data:'hahaha'+Math.random()});
6
+ let act = actions.shift();
7
+
8
+ console.log('act', act)
9
+ _do(mainTaskInfo, actions, callback);
10
+ };
11
+
12
+
13
+ class TestConsumer extends SuperConsumer {
14
+
15
+ // constructor
16
+ constructor(taskname, parentfolder) {
17
+ super(taskname, parentfolder)
18
+
19
+ }
20
+ setTaskTrunkInfo(trunkInfo){
21
+ this.trunkInfo = trunkInfo;
22
+ }
23
+ run (mainTaskInfo, subTaskInfo, taskInfo, callback){
24
+ let actions = subTaskInfo.actions;
25
+ mainTaskInfo.defination = this.trunkInfo.defination;
26
+ _do(mainTaskInfo, actions, (result)=>{
27
+ callback(result)
28
+ })
29
+
30
+ }
31
+ }
32
+ module.exports = TestConsumer;
@@ -0,0 +1,29 @@
1
+ let SuperProducer = require('multi-task').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
+ return new Promise((resolve, reject)=>{
15
+ let trunkInfo = this.trunkInfo;
16
+ //console.log(this.trunkInfo)
17
+ //throw repos.length+'ff'+repos2.length
18
+ //here, IGNORED_repoRegexStringList
19
+ let alltasks = []
20
+ for(let i=0;i<100;i++){
21
+ alltasks.push({
22
+ num:i
23
+ })
24
+ }
25
+ resolve(alltasks);
26
+ })
27
+ }
28
+ }
29
+ module.exports = TestProducer;
package/example/run.js ADDED
@@ -0,0 +1,26 @@
1
+ let fs = require('fs');
2
+ let _ = require('lodash');
3
+ let pathutil = require('path');
4
+ let RunnerProducer = require('./RunnerProducer')
5
+ let RunnerConsumer = require('./RunnerConsumer')
6
+
7
+ let taskId = Math.random()+'';
8
+ let multi_task_parent_folder = pathutil.resolve(__dirname, `../../../tasks-search-keywords`);
9
+
10
+ let producer = new RunnerProducer(`workers_of_${taskId}`, multi_task_parent_folder)
11
+ let consumer = new RunnerConsumer();
12
+ let master = require('multi-task').master;
13
+
14
+ console.log(producer.getTaskName())
15
+ //return;
16
+
17
+ let taskConfig = {
18
+ multi_task_parent_folder
19
+ }
20
+ //console.log(resp)
21
+ producer.setTaskTrunkInfo(taskConfig);
22
+ consumer.setTaskTrunkInfo(taskConfig)
23
+ master.run(producer, consumer, {
24
+ quotaOfEachTask:2,
25
+ numberOfWorks: 6
26
+ });
package/index.js ADDED
@@ -0,0 +1,8 @@
1
+ const SuperProducer = require('./workers/SuperProducer');
2
+ const SuperConsumer = require('./workers/SuperConsumer');
3
+ const master = require('./workers/master')
4
+ module.exports = {
5
+ SuperProducer,
6
+ SuperConsumer,
7
+ master
8
+ }
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "multi-tasks",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "directories": {
7
+ "example": "example"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [
13
+ "multitask",
14
+ "worker",
15
+ "multithread"
16
+ ],
17
+ "author": "zhanglei923@gmail.com",
18
+ "license": "MIT"
19
+ }
@@ -0,0 +1,57 @@
1
+ let fs = require('fs');
2
+ let pathutil = require('path');
3
+ class SuperConsumer {
4
+ // constructor
5
+ constructor(mainid, subid) {
6
+ this.mainid = mainid;
7
+ this.subid = subid;
8
+ }
9
+ run (taskInfo, callback){
10
+ //rewrite this
11
+ let succ = (Math.random()*1000)%3===0?true:false;
12
+ let result = {
13
+ succ
14
+ }
15
+ callback(result);
16
+ }
17
+ runTasks (mainTaskInfo, subTaskInfo, message){
18
+ // console.log(`mainTaskInfo:`, mainTaskInfo)
19
+ // console.log(`subTaskInfo:`, subTaskInfo)
20
+ // console.log(`message:`, message)
21
+
22
+ this.mainTaskInfo = mainTaskInfo;
23
+ this.subTaskInfo = subTaskInfo;
24
+
25
+ return new Promise((resolve, reject)=>{
26
+ let mainid = mainTaskInfo.masterTaskId;
27
+ let subid = subTaskInfo.subid;
28
+ let taskfolderNew = mainTaskInfo.taskFolderNew;
29
+ let taskFolderResult = mainTaskInfo.taskFolderResult;
30
+ this.mvTask(mainid, subid,'new','running', (taskFile)=>{//mark as running
31
+ let taskContent = fs.readFileSync(taskFile, 'utf8');
32
+ let taskInfo = JSON.parse(taskContent);
33
+ this.run(mainTaskInfo, subTaskInfo, taskInfo, (taskReport)=>{//invoke
34
+ let resultfile = pathutil.resolve(taskFolderResult, `${subid}.json`)
35
+ fs.writeFileSync(resultfile, JSON.stringify(taskReport));
36
+ this.mvTask(mainid, subid,'running','finished', ()=>{//mark as finished
37
+ resolve({
38
+ mainid,
39
+ subid,
40
+ ...message
41
+ })
42
+ });
43
+ });
44
+ });
45
+ });
46
+ }
47
+ mvTask (mainid, subid, from, to, callback) {
48
+ let __thisdir = this.mainTaskInfo.taskFolder;
49
+ let oldPath = pathutil.resolve(__thisdir, `./${from}/${subid}.task.json`);
50
+ let newPath = pathutil.resolve(__thisdir, `./${to}/${subid}.task.json`);
51
+ fs.rename(oldPath, newPath, (err) => {
52
+ if (err) throw err;
53
+ callback(newPath);
54
+ });
55
+ }
56
+ }
57
+ module.exports = SuperConsumer;
@@ -0,0 +1,70 @@
1
+ let fs = require('fs');
2
+ let moment = require('moment');
3
+ let pathutil = require('path');
4
+ let makeDir = require('make-dir');
5
+ let splitter = require('./taskSplitter');
6
+ class SuperProducer {
7
+ // constructor
8
+ constructor(taskname, parentfolder) {
9
+ this.taskname = taskname;
10
+ this.parentfolder = parentfolder;
11
+
12
+ }
13
+
14
+ getTaskName(){
15
+ return this.taskname;
16
+ }
17
+ getAllActions (){
18
+ //rewrite this method and return all your actions need to run
19
+ return new Promise();
20
+ }
21
+ generateTasks (quota, callback){
22
+ if(typeof quota === 'undefined' || !quota)quota=10;
23
+ let dateTimeText = moment().format('YYYY-MM-DD_HH-mm-ss');
24
+ let masterTaskId = `${this.taskname}_${dateTimeText}`;
25
+ console.log('masterTaskId=',masterTaskId);
26
+ this.taskfolder = pathutil.resolve(this.parentfolder, masterTaskId)
27
+ let taskFolder = this.taskfolder;
28
+ //let taskfolder = pathutil.parse(__filename).dir;
29
+ //let taskFolder = pathutil.resolve(taskfolder, `./tasks/${masterTaskId}`);
30
+ let taskFolderNew = pathutil.resolve(taskFolder, './new');
31
+ let taskFolderRunning = pathutil.resolve(taskFolder, './running');
32
+ let taskFolderFinished = pathutil.resolve(taskFolder, './finished');
33
+ let taskFolderResult = pathutil.resolve(taskFolder, './result');
34
+ //let mainRptFolder = pathutil.resolve(taskfolder, './report');
35
+
36
+ //makeDir.sync(mainRptFolder);
37
+ makeDir.sync(taskFolderNew);
38
+ makeDir.sync(taskFolderRunning);
39
+ makeDir.sync(taskFolderFinished);
40
+ makeDir.sync(taskFolderResult);
41
+
42
+ this.getAllActions().then((allactions)=>{
43
+
44
+ let allSubTasks = splitter.split(allactions, quota);
45
+
46
+
47
+ console.log('allSubTasks=', allSubTasks.length)
48
+
49
+ allSubTasks.forEach((info, i)=>{
50
+ let subid = i;
51
+ info.subid = subid;
52
+ let taskfilepath = pathutil.resolve(taskFolderNew, `./${info.subid}.task.json`);
53
+ fs.writeFileSync(taskfilepath, JSON.stringify(info));
54
+ });
55
+
56
+ callback({
57
+ masterTaskId,
58
+ allSubTasks,
59
+ //mainRptFolder,
60
+ taskFolder,
61
+ taskFolderNew,
62
+ taskFolderRunning,
63
+ taskFolderFinished,
64
+ taskFolderResult,
65
+ });
66
+ });
67
+ }
68
+ }
69
+
70
+ module.exports = SuperProducer;
@@ -0,0 +1,128 @@
1
+ var fs = require('fs');
2
+ var pathutil = require('path');
3
+ const cluster = require('cluster');
4
+ const numCPUs = require('os').cpus().length;
5
+ let moment = require('moment');
6
+
7
+
8
+ let MSG_REQUEST_TASKID = 'request_taskid';
9
+ /**
10
+ * masterId, the id of scanning flow
11
+ * -master, a master is a host of child_process computing
12
+ * -masterTaskId, id of a master, will rename to masterId
13
+ * -task, a child computing process
14
+ */
15
+
16
+ let getDateTimeTxt = ()=>{
17
+ return moment().format('YYYY-MM-DD HH:mm:ss');
18
+ };
19
+ let workidlist = new Set();
20
+ let addWorker = (wid)=>{
21
+ wid = wid+'';
22
+ workidlist.add(wid);
23
+ };
24
+ let removeWorker = (wid)=>{
25
+ wid = wid+'';
26
+ workidlist.delete(wid);
27
+ };
28
+ let hasWorker = ()=>{
29
+ return workidlist.size !== 0;
30
+ }
31
+ let run = (currentProducer, currentConsumer, opt)=>{
32
+ if(typeof opt === 'undefined') opt = {
33
+ quotaOfEachTask: 10
34
+ };
35
+ let masterId = currentProducer.getTaskName();
36
+ if(typeof opt.numberOfWorks === 'undefined') opt.numberOfWorks = numCPUs;
37
+ console.log('master1, masterId=', masterId)
38
+
39
+
40
+ if(!masterId) throw `***Must assign masterId, pls use run.sh to run!***`
41
+
42
+ console.log('start', getDateTimeTxt())
43
+
44
+ if (cluster.isMaster) {//init
45
+ let numWorks = opt.numberOfWorks;
46
+ console.log(`numCPUs ${numCPUs}`);
47
+ console.log(`numWorks ${numWorks}`);
48
+ console.log(`Master=${process.pid}`);
49
+
50
+ currentProducer.generateTasks(opt.quotaOfEachTask, (mainTaskInfo)=>{
51
+ //get ready
52
+ taskStack = mainTaskInfo.allSubTasks;
53
+ let totalTaskNum = taskStack.length;
54
+ console.log( 'tasks=', mainTaskInfo.masterTaskId);
55
+ console.log( 'totalTaskNum=', totalTaskNum);
56
+
57
+ for (let i = 0; i < numWorks; i++) {
58
+ let worker = cluster.fork();
59
+ addWorker(worker.id)
60
+ worker.on('message', function(message) {
61
+ //console.log(`(master).${process.pid} got: '${JSON.stringify(message)}' from w.${worker.process.pid}`);
62
+ if(message === MSG_REQUEST_TASKID){
63
+ if(taskStack.length > 0){
64
+ let subTaskInfo = taskStack.shift();
65
+ worker.send({
66
+ startTimestamp: new Date()*1,
67
+ mainTaskInfo,
68
+ subTaskInfo,
69
+ totalTaskNum
70
+ })
71
+ }else{
72
+ removeWorker(worker.id)
73
+ worker.kill();
74
+ console.log('no task left.', getDateTimeTxt());
75
+ if(!hasWorker()){
76
+ console.log('all done!')
77
+ let taskFolder = mainTaskInfo.taskFolder;
78
+ let dataForNextMission = {
79
+ ...mainTaskInfo
80
+ };
81
+ let dataPath = pathutil.resolve(taskFolder, `./extractTaskData-${masterId}.json`);
82
+ fs.writeFileSync(dataPath, JSON.stringify(dataForNextMission))
83
+ console.log('dataForNextMission=', dataPath)
84
+ };
85
+ }
86
+ }
87
+ });
88
+ }
89
+ });
90
+
91
+
92
+ } else {
93
+ let worker = cluster.worker;
94
+ //console.log(`>[w]=${process.pid} started`);
95
+ process.on('message', function(message) {});
96
+ worker.on('message', function(message) {
97
+ if(message.subTaskInfo){
98
+ let mainTaskInfo = message.mainTaskInfo;
99
+ let subTaskInfo = message.subTaskInfo;
100
+ let subid = subTaskInfo.subid;
101
+ if(mainTaskInfo){
102
+ console.log(`[Task Start]: "${subid}"`, `${subid}/${message.totalTaskNum}`, `pid=${process.pid}`, getDateTimeTxt());
103
+ //fs.writeFileSync(pathutil.resolve(mainTaskInfo.taskFolderFinished, `./${subid}`), subTaskInfo.tasksLen);
104
+ if(0){//mock
105
+ setTimeout(()=>{
106
+ worker.send(MSG_REQUEST_TASKID);//request new task
107
+ }, 100);
108
+ }else{//real
109
+ currentConsumer.runTasks(mainTaskInfo, subTaskInfo, message).then((report)=>{
110
+ let endTimestamp = new Date()*1;
111
+ let cost = report.startTimestamp - endTimestamp;
112
+
113
+ console.log(`[Task Finished] "${report.mainid}"."${report.subid}".`, getDateTimeTxt(), `cost=${cost}ms`)
114
+ worker.send(MSG_REQUEST_TASKID);//request new task
115
+ });
116
+ }
117
+ }else{
118
+ console.log('Can not find: message.subTaskInfo')
119
+ }
120
+ }
121
+ });
122
+ worker.send(MSG_REQUEST_TASKID);//request new task
123
+
124
+ }
125
+ }
126
+ module.exports = {
127
+ run
128
+ };
@@ -0,0 +1,30 @@
1
+ let split = (list, quota)=>{
2
+ let totalFilesLen = list.length
3
+ console.log('total:', totalFilesLen,'actions');
4
+ let allSubTasks = [];
5
+ let actions = [];
6
+ let currentIdx = 0;
7
+ let subid = 0;
8
+ list.forEach((act)=>{
9
+ currentIdx++;
10
+ actions.push(act)
11
+ if(actions.length>=quota){
12
+ allSubTasks.push({
13
+ actions,
14
+ tasksLen: actions.length
15
+ });
16
+ actions = [];
17
+ subid++;
18
+ }else if(totalFilesLen === currentIdx){
19
+ allSubTasks.push({
20
+ actions,
21
+ tasksLen: actions.length
22
+ });
23
+ }
24
+ //console.log(totalFilesLen,'-', currentIdx)
25
+ });
26
+ return allSubTasks;
27
+ }
28
+ module.exports = {
29
+ split
30
+ }
@@ -0,0 +1,25 @@
1
+ let SuperConsumer = require('../SuperConsumer');
2
+ class TestConsumer extends SuperConsumer {
3
+
4
+ // constructor
5
+ constructor(taskname, parentfolder) {
6
+ super(taskname, parentfolder)
7
+
8
+ }
9
+ run (mainTaskInfo, subTaskInfo, taskInfo, callback){
10
+ //do job
11
+ // console.log(`mainTaskInfo:`, mainTaskInfo)
12
+ // console.log(`subTaskInfo:`, subTaskInfo)
13
+ // console.log(`taskInfo:`, taskInfo)
14
+ //return;
15
+ //rewrite this
16
+ let succ = (Math.random()*1000)%3===0?true:false;
17
+ let result = {
18
+ succ
19
+ }
20
+ setTimeout(()=>{
21
+ callback(result);
22
+ }, Math.random()*1000)
23
+ }
24
+ }
25
+ module.exports = TestConsumer;
@@ -0,0 +1,26 @@
1
+ let SuperProducer = require('../SuperProducer');
2
+ class TestProducer extends SuperProducer {
3
+
4
+ // constructor
5
+ constructor(taskname, parentfolder) {
6
+ super(taskname, parentfolder)
7
+
8
+ }
9
+ getAllActions() {
10
+ return new Promise((resolve, reject)=>{
11
+ setTimeout(()=>{
12
+
13
+
14
+ let alltasks = []
15
+ for(let i=0;i<1673;i++){
16
+ alltasks.push({
17
+ xxx:111,
18
+ zzz:222
19
+ })
20
+ }
21
+ resolve(alltasks);
22
+ }, 3000)
23
+ });
24
+ }
25
+ }
26
+ module.exports = TestProducer;
@@ -0,0 +1,12 @@
1
+ let MyProducer = require('./MyProducer')
2
+ let MyConsumer = require('./MyConsumer')
3
+ let producer = new MyProducer(`atasknametest`, `D:\\tmp`)
4
+ let consumer = new MyConsumer()
5
+ let master = require('../master')
6
+
7
+
8
+ master.run(producer, consumer, {
9
+
10
+ quotaOfEachTask: 3
11
+
12
+ })
@@ -0,0 +1,4 @@
1
+ let TestProducer = require('./MyProducer')
2
+ let producer = new TestProducer(`tasknametest`, `D:\\tmp`)
3
+
4
+ producer.generateTasks()
@@ -0,0 +1,7 @@
1
+ let splitter = require('../taskSplitter');
2
+ let alltasks = []
3
+ for(let i=0;i<16;i++){
4
+ alltasks.push(i)
5
+ }
6
+ let subtasks = splitter.split(alltasks, 5);
7
+ console.log(subtasks)