Skip to content

Commit 29a4ad6

Browse files
committed
fix listen_timeout associated with wait_ready \Unitech#2956
1 parent 8980bae commit 29a4ad6

File tree

7 files changed

+173
-8
lines changed

7 files changed

+173
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- `--instances -1` when having a 1 cpu is no-longer spawning no processes #2953
55
- refactor the context retrieving from error
66
- add a TTL for file cache entry
7+
- #2956 Fix listen_timeout in combination with wait_ready
78

89
## 2.5
910

examples/wait-ready/app.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ console.log('Starting app...');
1111

1212
process.on('SIGINT', (msg) => {
1313
console.log('Just got SIGINTed, but I dont care');
14+
process.exit(0);
1415
});
1516

1617
setTimeout(() => {

examples/wait-ready/ecosystem.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
"instances": 2,
66
"exec_mode": "cluster",
77
"wait_ready": true,
8-
"listen_timeout": 15000
8+
"listen_timeout": 16000
99
}]
1010
}

lib/God.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,22 @@ God.executeApp = function executeApp(env, cb) {
196196
if (!clu.pm2_env.wait_ready)
197197
return readyCb(clu);
198198

199+
// Timeout if the ready message has not been sent before listen_timeout
200+
var ready_timeout = setTimeout(function() {
201+
God.bus.removeListener('process:msg', listener)
202+
return readyCb(clu)
203+
}, clu.pm2_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
204+
199205
var listener = function (packet) {
200-
if (packet.raw === 'ready' && packet.process.name === clu.pm2_env.name && packet.process.pm_id === clu.pm2_env.pm_id) {
206+
if (packet.raw === 'ready' &&
207+
packet.process.name === clu.pm2_env.name &&
208+
packet.process.pm_id === clu.pm2_env.pm_id) {
209+
clearTimeout(ready_timeout);
201210
God.bus.removeListener('process:msg', listener)
202211
return readyCb(clu)
203212
}
204213
}
214+
205215
God.bus.on('process:msg', listener);
206216
});
207217
});
@@ -217,11 +227,11 @@ God.executeApp = function executeApp(env, cb) {
217227
var old_env = God.clusters_db[clu.pm2_env.pm_id];
218228
if (old_env) old_env = null;
219229

220-
var proc = God.clusters_db[env_copy.pm_id] = clu;
230+
God.clusters_db[env_copy.pm_id] = clu;
221231

222232
clu.once('error', function cluError(err) {
223233
console.error(err.stack || err);
224-
proc.pm2_env.status = cst.ERRORED_STATUS;
234+
clu.pm2_env.status = cst.ERRORED_STATUS;
225235
try {
226236
clu.kill && clu.kill();
227237
}
@@ -235,14 +245,23 @@ God.executeApp = function executeApp(env, cb) {
235245
if (clu.connected === true)
236246
clu.disconnect && clu.disconnect();
237247
clu._reloadLogs = null;
238-
return God.handleExit(proc, code || 0, signal);
248+
return God.handleExit(clu, code || 0, signal);
239249
});
240250

241251
if (!clu.pm2_env.wait_ready)
242252
return readyCb(clu);
243253

254+
// Timeout if the ready message has not been sent before listen_timeout
255+
var ready_timeout = setTimeout(function() {
256+
God.bus.removeListener('process:msg', listener)
257+
return readyCb(clu)
258+
}, clu.pm2_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
259+
244260
var listener = function (packet) {
245-
if (packet.raw === 'ready' && packet.process.name === proc.pm2_env.name && packet.process.pm_id === proc.pm2_env.pm_id) {
261+
if (packet.raw === 'ready' &&
262+
packet.process.name === clu.pm2_env.name &&
263+
packet.process.pm_id === clu.pm2_env.pm_id) {
264+
clearTimeout(ready_timeout);
246265
God.bus.removeListener('process:msg', listener)
247266
return readyCb(clu)
248267
}

test/bash/wait-ready-event.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ should 'should have started 1 forked app ' 'online' 1
2121
$pm2 delete all
2222

2323
##### start without sending event and ask to wait (fork mode)
24-
timeout 5 $pm2 start http-wait-start_nocb.js --wait-ready
24+
timeout 5 $pm2 start http-wait-start_nocb.js --wait-ready --listen-timeout=8000
2525
should 'should be 1 forked launching state app waiting for ready event' 'launching' 1
2626
$pm2 delete all
2727

@@ -41,6 +41,6 @@ should 'should have started 1 clustered app' 'online' 1
4141
$pm2 delete all
4242

4343
##### start without sending event and ask to wait (cluster mode)
44-
timeout 5 $pm2 start http-wait-start_nocb.js -i 1 --wait-ready
44+
timeout 5 $pm2 start http-wait-start_nocb.js -i 1 --wait-ready --listen-timeout=8000
4545
should 'should be 1 clustered launching state app waiting for ready event' 'launching' 1
4646
$pm2 delete all

test/pm2_programmatic_tests.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ mocha --opts ./mocha.opts ./module_configuration.mocha.js
6060
spec "Max memory tests"
6161
mocha --opts ./mocha.opts ./cluster.mocha.js
6262
spec "Cluster tests"
63+
mocha --opts ./mocha.opts ./graceful.mocha.js
64+
spec "Graceful tests"
6365
mocha --opts ./mocha.opts ./inside.mocha.js
6466
spec "Inside pm2 call tests"
6567
mocha --opts ./mocha.opts ./misc_commands.js

test/programmatic/graceful.mocha.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
2+
process.env.NODE_ENV = 'test';
3+
4+
var PM2 = require('../..');
5+
var should = require('should');
6+
var path = require('path');
7+
var Plan = require('../helpers/plan.js');
8+
9+
process.chdir(__dirname);
10+
11+
describe('Wait ready / Graceful start / restart', function() {
12+
this.timeout(5000);
13+
14+
var pm2 = new PM2.custom({
15+
cwd : '../fixtures/listen-timeout/',
16+
independent : true
17+
});
18+
19+
after(function(done) {
20+
pm2.destroy(done)
21+
});
22+
23+
describe('(FORK) Listen timeout feature', function() {
24+
this.timeout(10000);
25+
26+
after(function(done) {
27+
pm2.delete('all', done);
28+
});
29+
30+
it('should force script to set as ready after forced listen_timeout', function(done) {
31+
pm2.start({
32+
script : './wait-ready.js',
33+
listen_timeout : 1000,
34+
wait_ready : true,
35+
name : 'echo'
36+
});
37+
38+
setTimeout(function() {
39+
pm2.list(function(err, apps) {
40+
should(apps[0].pm2_env.status).eql('launching');
41+
});
42+
}, 800);
43+
44+
setTimeout(function() {
45+
pm2.list(function(err, apps) {
46+
should(apps[0].pm2_env.status).eql('online');
47+
done();
48+
})
49+
}, 1500);
50+
});
51+
52+
it('should have listen timeout updated', function(done) {
53+
pm2.list(function(err, list) {
54+
should(list[0].pm2_env.wait_ready).eql(true);
55+
done();
56+
});
57+
});
58+
59+
it('should take listen timeout into account', function(done) {
60+
var called = false;
61+
var plan = new Plan(3, done);
62+
63+
setTimeout(function() {
64+
should(called).be.false();
65+
plan.ok(true);
66+
}, 300);
67+
68+
setTimeout(function() {
69+
should(called).be.true();
70+
plan.ok(true);
71+
}, 1500);
72+
73+
pm2.reload('all', function(err, data) {
74+
called = true;
75+
plan.ok(true);
76+
});
77+
});
78+
79+
it('should restart script with different listen timeout', function(done) {
80+
pm2.restart({
81+
script : './echo.js',
82+
listen_timeout : 100,
83+
instances : 1,
84+
name : 'echo'
85+
}, done);
86+
});
87+
88+
it('should have listen timeout updated', function(done) {
89+
pm2.list(function(err, list) {
90+
should(list[0].pm2_env.listen_timeout).eql(100);
91+
should(list.length).eql(1);
92+
done();
93+
});
94+
});
95+
96+
it('should be reloaded after 100ms', function(done) {
97+
var called = false;
98+
99+
setTimeout(function() {
100+
should(called).be.true();
101+
done();
102+
}, 500);
103+
104+
pm2.reload('all', function(err, data) {
105+
called = true;
106+
});
107+
});
108+
});
109+
110+
111+
describe('(CLUSTER) Listen timeout feature', function() {
112+
this.timeout(10000);
113+
114+
after(function(done) {
115+
pm2.delete('all', done);
116+
});
117+
118+
it('should force script to set as ready after forced listen_timeout', function(done) {
119+
pm2.start({
120+
script : './wait-ready.js',
121+
listen_timeout : 1000,
122+
wait_ready : true,
123+
instances : 2,
124+
name : 'echo'
125+
});
126+
127+
setTimeout(function() {
128+
pm2.list(function(err, apps) {
129+
should(apps[0].pm2_env.status).eql('launching');
130+
});
131+
}, 800);
132+
133+
setTimeout(function() {
134+
pm2.list(function(err, apps) {
135+
should(apps[0].pm2_env.status).eql('online');
136+
done();
137+
})
138+
}, 1500);
139+
});
140+
});
141+
142+
});

0 commit comments

Comments
 (0)