forked from foreversd/forever
/
worker.js
122 lines (97 loc) · 2.88 KB
/
worker.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
111
112
113
114
115
116
117
118
119
120
121
var events = require('events'),
fs = require('fs'),
path = require('path'),
nssocket = require('nssocket'),
utile = require('utile'),
forever = require(path.resolve(__dirname, '..', 'forever'));
var Worker = exports.Worker = function (options) {
events.EventEmitter.call(this);
options || (options = {});
this.monitor = options.monitor;
this.sockPath = options.sockPath || forever.config.get('sockPath');
this.exitOnStop = options.exitOnStop === true;
this._socket = null;
};
utile.inherits(Worker, events.EventEmitter);
Worker.prototype.start = function (callback) {
var self = this,
err;
if (this._socket) {
err = new Error("Can't start already started worker");
if (callback) {
return callback(err);
}
throw err;
}
//
// Defines a simple `nssocket` protocol for communication
// with a parent process.
//
function workerProtocol(socket) {
socket.on('error', function() {
socket.destroy();
})
socket.data(['ping'], function () {
socket.send(['pong']);
});
socket.data(['data'], function () {
socket.send(['data'], self.monitor.data);
});
socket.data(['spawn'], function (data) {
if (!data.script) {
return socket.send(['spawn', 'error'], { error: new Error('No script given') });
}
if (self.monitor) {
return socket.send(['spawn', 'error'], { error: new Error("Already running") });
}
var monitor = new (forever.Monitor)(data.script, data.options);
monitor.start();
monitor.on('start', function () {
socket.send(['spawn', 'start'], monitor.data);
});
});
socket.data(['stop'], function () {
self.monitor.once('stop', function () {
socket.send(['stop', 'ok']);
self.exitOnStop && process.exit();
});
self.monitor.stop();
});
socket.data(['restart'], function () {
self.monitor.once('restart', function () {
socket.send(['restart', 'ok']);
});
self.monitor.restart();
});
}
function findAndStart() {
self._socket = nssocket.createServer(workerProtocol);
self._socket.on('listening', function () {
//
// `listening` listener doesn't take error as the first parameter
//
self.emit('start');
callback && callback(null, self._sockFile);
});
self._socket.on('error', function (err) {
if (err.code === 'EADDRINUSE') {
return findAndStart();
}
callback && callback(err);
});
//
// Create a unique socket file based on the current microtime.
//
var sock = self._sockFile = path.join(self.sockPath, [
'worker',
new Date().getTime() + utile.randomString(3),
'sock'
].join('.'));
self._socket.listen(sock);
}
//
// Attempt to start the server the first time
//
findAndStart();
return this;
};