From f4d4451eeb55a8d1ca89a6e1c73eaefd4699be7b Mon Sep 17 00:00:00 2001 From: nuintun Date: Thu, 3 Dec 2015 10:19:09 +0800 Subject: [PATCH] update files --- bin/emulator.js | 63 +------- bin/thread.js | 70 +++++++++ main.js | 197 +++++++++++++++---------- static/js/components/app-main/index.js | 17 ++- 4 files changed, 204 insertions(+), 143 deletions(-) create mode 100644 bin/thread.js diff --git a/bin/emulator.js b/bin/emulator.js index 59a1199..77d94f1 100644 --- a/bin/emulator.js +++ b/bin/emulator.js @@ -4,8 +4,6 @@ 'use strict'; -var ipc = require('ipc-main'); - var spawn = require('child_process').spawn; /** @@ -71,64 +69,5 @@ function normalizeExecArgs(command, options){ }; } -var emulators = {}; +module.exports = Emulator; -module.exports = { - Emulator: Emulator, - start: function (){ - ipc.on('emulator', function (event, project, action){ - var key = project.name + '-' + project.command.name; - var emulator = emulators[key]; - - switch (action) { - case 'start': - if (!emulator) { - var stream; - var env = {}; - - Object.keys(process.env).forEach(function (key){ - env[key] = process.env[key]; - }); - - project.env.forEach(function (item){ - env[item.name] = item.value; - }); - - emulator = new Emulator({ - env: env, - cwd: project.path, - command: project.command.value - }); - - stream = emulator.start(); - - stream.stdout.on('data', function (data){ - event.sender.send('emulator', 'data', project, data); - }); - - stream.stderr.on('error', function (error){ - event.sender.send('emulator', 'error', project, error); - - emulator.stop(); - - delete emulators[key]; - }); - - stream.on('close', function (signal){ - event.sender.send('emulator', 'close', project, signal); - - delete emulators[key]; - }); - - emulators[key] = emulator; - } - break; - case 'stop': - if (emulator) { - emulator.stop(); - } - break; - } - }); - } -}; diff --git a/bin/thread.js b/bin/thread.js new file mode 100644 index 0000000..6aabcff --- /dev/null +++ b/bin/thread.js @@ -0,0 +1,70 @@ +/** + * Created by nuintun on 2015/12/3. + */ + +'use strict'; + +var cluster = require('cluster'); + +var ipc = require('ipc-main'); + +// cache +var workers = {}; + +/** + * killWorker + * @param name + */ +function killWorker(name){ + var worker = workers[name]; + + if (worker && !worker.isDead()) { + worker.kill('SIGTERM'); + + delete workers[name]; + } +} + +module.exports = { + start: function (){ + ipc.on('emulator', function (event, project, action){ + var key = project.name + '-' + project.command.name; + var worker = workers[key]; + + switch (action) { + case 'start': + if (!worker) { + var env = {}; + + Object.keys(process.env).forEach(function (key){ + env[key] = process.env[key]; + }); + + project.env.forEach(function (item){ + env[item.name] = item.value; + }); + + worker = cluster.fork(env); + + worker.on('message', function (message){ + event.sender.send('emulator', message.event, message.project, message.data); + }); + + worker.on('error', function (){ + killWorker(project.name); + }); + + delete project.env; + + worker.send(project); + + workers[project.name] = worker; + } + break; + case 'stop': + killWorker(project.name); + break; + } + }); + } +}; diff --git a/main.js b/main.js index 3dfc1a7..567011e 100644 --- a/main.js +++ b/main.js @@ -4,91 +4,134 @@ 'use strict'; -// node module -var path = require('path'); -// module to control application life -var app = require('app'); -var Menu = require('menu'); -var Tray = require('tray'); -// module to create native browser window -var BrowserWindow = require('browser-window'); -// custom module -var windowControl = require('./bin/window-control'); -var openDirectory = require('./bin/open-directory'); -var AppConfigure = require('./bin/app-configure'); -var emulator = require('./bin/emulator'); +var cluster = require('cluster'); -// keep a global reference of the window object, if you don't, the window will -// be closed automatically when the javascript object is GCed -var mainTray = null; -var mainWindow = null; -// const var -const APPNAME = '命令管理器'; -const ICON = path.join(__dirname, './app.ico'); -const INDEX = 'file:///' + path.join(__dirname, 'index.html'); +if (cluster.isMaster) { + // node module + var path = require('path'); + // module to control application life + var app = require('app'); + var Menu = require('menu'); + var Tray = require('tray'); + // module to create native browser window + var BrowserWindow = require('browser-window'); + // custom module + var windowControl = require('./bin/window-control'); + var openDirectory = require('./bin/open-directory'); + var AppConfigure = require('./bin/app-configure'); + var thread = require('./bin/thread'); -// quit when all windows are closed -app.on('window-all-closed', function (){ - app.quit(); -}); + // keep a global reference of the window object, if you don't, the window will + // be closed automatically when the javascript object is GCed + var mainTray = null; + var mainWindow = null; + // const var + const APPNAME = '命令管理器'; + const ICON = path.join(__dirname, './app.ico'); + const INDEX = 'file:///' + path.join(__dirname, 'index.html'); -// this method will be called when atom-shell has done everything -// initialization and ready for creating browser windows -app.on('ready', function (){ - // create the tray window - mainTray = new Tray(ICON); - - mainTray.setToolTip(APPNAME); - mainTray.setContextMenu(Menu.buildFromTemplate([ - { - label: '显示窗口', - click: function (){ - mainWindow.show(); - } - }, - { - label: '退出程序', - click: function (){ - app.quit(); - } - } - ])); - - // create the browser window - mainWindow = new BrowserWindow({ - width: 1024, - height: 768, - icon: ICON, - 'min-width': 1024, - 'min-height': 768, - title: APPNAME, - frame: false, - center: true, - 'use-content-size': true + // quit when all windows are closed + app.on('window-all-closed', function (){ + app.quit(); }); - // and load the index.html of the app - mainWindow.loadURL(INDEX); - // emitted when the window is closed - mainWindow.on('closed', function (){ - // dereference the window object, usually you would store windows - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element - mainTray.destroy(); + // this method will be called when atom-shell has done everything + // initialization and ready for creating browser windows + app.on('ready', function (){ + // create the tray window + mainTray = new Tray(ICON); - mainTray = null; - mainWindow = null; + mainTray.setToolTip(APPNAME); + mainTray.setContextMenu(Menu.buildFromTemplate([ + { + label: '显示窗口', + click: function (){ + mainWindow.show(); + } + }, + { + label: '退出程序', + click: function (){ + app.quit(); + } + } + ])); + + // create the browser window + mainWindow = new BrowserWindow({ + width: 1024, + height: 768, + icon: ICON, + 'min-width': 1024, + 'min-height': 768, + title: APPNAME, + frame: false, + center: true, + 'use-content-size': true + }); + + // and load the index.html of the app + mainWindow.loadURL(INDEX); + // emitted when the window is closed + mainWindow.on('closed', function (){ + // dereference the window object, usually you would store windows + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element + mainTray.destroy(); + + mainTray = null; + mainWindow = null; + }); + + // window control + windowControl(ICON, mainWindow, mainTray); + + // open directory + openDirectory(mainWindow); + + // app configure + new AppConfigure(mainWindow, mainTray); + + // emulator start + thread.start(); }); +} else { + var Emulator = require('./bin/emulator'); - // window control - windowControl(ICON, mainWindow, mainTray); + process.on('message', function (project){ + var stream; - // open directory - openDirectory(mainWindow); + var emulator = new Emulator({ + cwd: project.path, + command: project.command.value + }); - // app configure - new AppConfigure(mainWindow, mainTray); + stream = emulator.start(); - // emulator start - emulator.start(); -}); + stream.stdout.on('data', function (data){ + process.send({ + event: 'data', + project: project, + data: data.toString() + }); + }); + + stream.stderr.on('error', function (error){ + emulator.stop(); + process.send({ + event: 'error', + project: project, + data: error.toString() + }); + }); + + stream.on('close', function (signal){ + emulator.stop(); + process.send({ + event: 'close', + project: project, + data: signal.toString() + }); + }); + }); +} diff --git a/static/js/components/app-main/index.js b/static/js/components/app-main/index.js index bb0babe..2d8a29c 100644 --- a/static/js/components/app-main/index.js +++ b/static/js/components/app-main/index.js @@ -143,10 +143,19 @@ module.exports = Vue.component('app-main', { }, methods: { exec: function (name, command){ + var project = this.project; + var runtime = AppRuntime[project.name]; + + runtime.worker.port.postMessage({ + action: 'write', + name: project.name, + data: '\u001b[32m执行命令\u001b[0m: \u001b[35m' + name + '\u001b[0m\r\n' + }); + ipc.send('emulator', { - name: this.project.name, - path: this.project.path, - env: util.normalize(this.project.env), + name: project.name, + path: project.path, + env: util.normalize(project.env), command: { name: name, value: command @@ -202,7 +211,7 @@ module.exports = Vue.component('app-main', { data = data.toString(); break; case 'error': - data = '\u001b[31m发生错误: \u001b[0m' + data.toString(); + data = '\u001b[31m发生错误: \u001b[0m' + data.toString(); break; case 'close': data = '\u001b[32m命令执行完成\u001b[0m';