dragonbones-runtime
Version:
the tools to build dragonbones file for diffrent framework
227 lines (182 loc) • 6.72 kB
text/typescript
/// <reference path="../lib/types.d.ts" />
import url = require('url');
import net = require('net');
import http = require('http');
import Project = require('./project');
import ServiceSocket = require('./ServiceSocket');
import file = require('../lib/FileUtil');
import childProcess = require('child_process');
import parser = require('../parser/Parser');
import os = require("os");
import { data as engineData } from "../EngineData";
var COMPILE_SERVICE_PORT = 51545;
//egret version, use to shutdown if the version is different to the value passed by the build command
var version = process.argv[2];
var projects = {};
var timer: NodeJS.Timer;
var lastBuildTime: number = Date.now();
export namespace server {
export var serviceCreated = false;
/**
* Start Egret Service
*/
export function run() {
var server = net.createServer(socket => {
var ss = new ServiceSocket(socket);
ss.on("message", msg => handleCommands(msg, ss));
});
try {
server.listen(COMPILE_SERVICE_PORT);
}
catch (e) {
console.error("Service.run", e);
}
process.on('uncaughtException', function (e: NodeJS.ErrnoException) {
console.log("未捕获的异常:", e);
if (e.code == 'EADDRINUSE') {
console.log(`无法启动 service, 请检查端口 ${COMPILE_SERVICE_PORT} 是否被占用。`)
}
});
process.on('exit', () => {
});
}
function handleCommands(task: egret.ServiceCommand, serviceSocket: ServiceSocket) {
console.log("得到任务:", task.command, task.path);
//|| task.version && task.version != version
if (task.command == 'shutdown') {
serviceSocket.send({});
internal_shutdown();
}
var proj: Project = getProject(task.path);
proj.option = parser.parseJSON(task.option);
if (task.command == 'init') {
proj.setServiceSocket(serviceSocket);
}
else if (task.command == 'build') {
// autoExitTimer();
var buildHandled = false;
if (task.option.added && task.option.added.length) {
task.option.added.forEach(file => proj.fileChanged(serviceSocket, task, file, "added"));
buildHandled = true;
}
if (task.option.removed && task.option.removed.length) {
task.option.removed.forEach(file => proj.fileChanged(serviceSocket, task, file, "removed"));
buildHandled = true;
}
if (task.option.modified && task.option.modified.length) {
task.option.modified.forEach(file => proj.fileChanged(serviceSocket, task, file, "modified"));
buildHandled = true;
}
if (!buildHandled)
proj.fileChanged(serviceSocket, task);
}
else if (task.command == 'status') {
var heapTotal: number = task['status']['heapTotal'];
heapTotal = heapTotal / 1024 / 1024;
heapTotal = heapTotal | 0;
console.log(`内存占用: ${heapTotal}M ${proj.path}`);
let totalmem = engineData.getTotalMem();
let maxHeap;
if (totalmem == -1) {
//取系统最大内存的四分之一,最低500M
maxHeap = Math.max(require("os").totalmem() / 1024 / 1024 / 4, 500);
}
else {
maxHeap = totalmem;
}
if (heapTotal > maxHeap) {
console.log("内存占用过高,关闭进程:" + proj.path);
proj.shutdown();
}
}
}
// function autoExitTimer() {
// lastBuildTime = Date.now();
// if (timer) {
// clearTimeout(timer);
// }
// timer = <any>setTimeout(shutdown, 10 * 60 * 1000);
// }
export function startBackgroundService() {
serviceCreated = true;
var cwd = os.tmpdir();
var options = egret.args;
var nodePath = process.execPath,
service = file.joinPath(egret.root, 'tools/bin/egret');
var startupParams = ['--expose-gc', service, 'service'];
if (egret.args.target) {
startupParams.push("--runtime", egret.args.target);
}
if (egret.args.experimental) {
startupParams.push("-exp");
}
var server = childProcess.spawn(nodePath, startupParams, {
detached: true,
stdio: ['ignore', 'ignore', 'ignore'],
cwd: cwd
});
server.on("exit", () => serviceCreated = false);
}
function internal_shutdown() {
for (var path in projects) {
var project: Project = projects[path];
project.shutdown();
}
process.exit(0);
}
function parseRequest(req: http.ServerRequest): egret.ServiceCommand {
var uri = url.parse(req.url, true);
var command = uri.query.q;
return JSON.parse(command) || {};
}
}
export namespace client {
/**
* Send command to Compile Service
*/
export function execCommand(command: egret.ServiceCommand, callback?: Function, startServer = true): ServiceSocket {
var options = egret.args;
var requestUrl = getServiceURL(command);
var client = net.connect(COMPILE_SERVICE_PORT, "127.0.0.1");
var ss = new ServiceSocket(client);
client.on('error', function (e) {
if (!startServer)
return;
if (!server.serviceCreated) {
server.startBackgroundService();
}
setTimeout(() => execCommand(command, callback), 200);
});
ss.on('message', cmd => callback && callback(cmd, ss));
ss.send(command);
return ss;
}
export function requestBuild() {
}
export function closeServer(path) {
return new Promise((reslove, reject) => {
execCommand({
path,
command: "shutdown",
option: egret.args
}, reslove, false);
})
}
function getServiceURL(params: any) {
var json = JSON.stringify(params);
return "http://127.0.0.1:" + COMPILE_SERVICE_PORT + "/?q=" + encodeURIComponent(json);
}
}
function getProject(path: string) {
if (!path)
return null;
var project: Project;
if (!projects[path]) {
project = new Project();
project.path = path;
project.init();
projects[path] = project;
return project;
}
return projects[path];
}