-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.js
110 lines (103 loc) · 3.1 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
var configs = require('configs');
var cluster = require('cluster');
var path = require('path');
var rollbar = require('rollbar');
var numCPUs = require('os').cpus().length;
var pluck = require('map-utils').pluck;
if (configs.newrelic) {
require('newrelic');
}
var workers;
var createWorker = function() {
var worker = cluster.fork();
worker.process.on('uncaughtException', function(err) {
console.error(new Date(), 'WORKER: uncaughtException:', err);
rollbar.handleError(err, function () {
worker.process.exit(1);
});
});
workers.push(worker);
console.log(new Date(), 'CLUSTER: create new worker', worker.id);
return worker;
};
var attachLogs = function(clusters) {
clusters.on('fork', function(worker) {
console.log(new Date(), 'CLUSTER: fork worker', worker.id);
});
clusters.on('listening', function(worker, address) {
console.log(new Date(), 'CLUSTER: listening worker', worker.id,
'address', address.address + ":" + address.port);
});
clusters.on('exit', function(worker, code, signal) {
console.log(new Date(), 'CLUSTER: exit worker', worker.id, 'code', code, 'signal', signal);
workers.map(pluck('id')).some(function (workerId, i) {
if (workerId === worker.id) {
workers.splice(i, 1); // remove worker from workers
}
});
createWorker();
});
clusters.on('online', function(worker) {
console.log(new Date(), 'CLUSTER: online worker', worker.id);
});
clusters.on('disconnect', function(worker) {
console.log(new Date(), 'CLUSTER: disconnected worker', worker.id, "killing now");
worker.kill();
});
};
var initExternalServices = function() {
if (configs.rollbar) {
rollbar.init(configs.rollbar, {
environment: process.env.NODE_ENV || "development",
branch: "master",
root: path.resolve(__dirname, '..')
});
}
};
var memoryLeakPatch = function() {
// memory leak patch! - start restart timeout
setInterval(killAndStartNewWorker, configs.workerRestartTime);
var onError = function(err) {
rollbar.handleError(err);
console.log(new Date(), "CLUSTER: error on disconnect", err);
};
function killAndStartNewWorker () {
var worker = workers.shift();
console.log(new Date(), 'CLUSTER: workaround disconnect worker', worker.id);
worker.disconnect();
worker.on('error', onError);
}
};
var masterHandleException = function(err) {
process.on('uncaughtException', function(err) {
if (configs.rollbar) {
rollbar.shutdown();
}
console.error(new Date(), 'MASTER: uncaughtException:', err);
rollbar.handleError(err, function() {
for (var id in cluster.workers) {
cluster.workers[id].kill('SIGTERM');
}
process.exit();
});
});
};
if (cluster.isMaster) {
attachLogs(cluster);
initExternalServices();
masterHandleException();
// Fork workers.
workers = [];
for (var i = 0; i < numCPUs; i++) {
createWorker();
}
memoryLeakPatch();
} else {
var api_server = require('index');
var apiServer = new api_server();
apiServer.start(function(err) {
if (err) {
console.error(new Date(), "can not start", err);
}
});
}