Skip to content

Commit dfcd1a8

Browse files
committed
feat: Cloud 函数和 Hook 函数增加 15 秒超时时间限制
因为 Node.js 存在大量的异步编程,导致很容易漏掉 http response 回调,使得服务处于不响应状态。增加超时限制会在超时时间达到且没有 响应时强制响应。 issue #574
1 parent 5d9532e commit dfcd1a8

3 files changed

Lines changed: 35 additions & 1 deletion

File tree

lib/leanengine.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var connect = require('connect'),
44
https = require('https'),
55
domain = require('domain'),
66
crypto = require('crypto'),
7+
timeout = require('connect-timeout'),
78
version = require('../package.json').version,
89
AV = require('./av-extra'),
910
utils = require('./utils'),
@@ -31,6 +32,8 @@ if (https.globalAgent && https.globalAgent.options) {
3132
https.globalAgent.options.rejectUnauthorized = false;
3233
}
3334

35+
var TIMEOUT = '15s';
36+
3437
AV.Cloud.CookieSession = avosExpressCookieSession(AV);
3538
AV.Cloud.HttpsRedirect = avosExpressHttpsRedirect(AV);
3639

@@ -59,6 +62,7 @@ Cloud.use('/__engine/1/ping', function(req, res) {
5962
next();
6063
});
6164

65+
Cloud.use(route, timeout(TIMEOUT));
6266
Cloud.use(route, bodyParser.urlencoded({extended: false}));
6367
Cloud.use(route, bodyParser.json());
6468
Cloud.use(route, bodyParser.text());
@@ -72,7 +76,7 @@ Cloud.use('/__engine/1/ping', function(req, res) {
7276
d.add(req);
7377
d.add(res);
7478
d.on('error', function(err) {
75-
console.error('LeanEngine function uncaughtException url=%s, msg=%s', req.url, err.stack || err.message || err);
79+
console.error('LeanEngine function uncaughtException url=%s, msg=%s', req.originalUrl, err.stack || err.message || err);
7680
if(!res.finished) {
7781
res.statusCode = 500;
7882
res.setHeader('content-type', 'application/json; charset=UTF-8');
@@ -261,6 +265,11 @@ Cloud.use('/__engine/1/ping', function(req, res) {
261265

262266
// next 参数即使不使用,也一定要存在,否则 error handler 不生效
263267
Cloud.use(route, function(err, req, res, next) { // jshint ignore:line
268+
if(req.timedout) {
269+
console.error('LeanEngine function timeout, url=%s, timeout=%d', req.originalUrl, err.timeout);
270+
err.code = 124; // https://leancloud.cn/docs/error_code.html#_124
271+
err.message = 'The request timed out on the server.';
272+
}
264273
respError(res, err);
265274
});
266275
});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"avoscloud-sdk": "0.x",
1111
"body-parser": "1.9.0",
1212
"connect": "3.2.0",
13+
"connect-timeout": "^1.7.0",
1314
"cookies": "0.5.0",
1415
"debug": "2.0.0",
1516
"iconv-lite": "^0.4.8",

test/function_test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ AV.Cloud.define("userMatching", function(req, res) {
211211
}, Math.floor((Math.random() * 2000) + 1));
212212
});
213213

214+
AV.Cloud.define('testTimeout', function(req, res) {
215+
setTimeout(function() {
216+
res.success('ok');
217+
}, req.params.delay);
218+
});
219+
214220
AV.Insight.on('end', function(err, result) {
215221
assert.deepEqual({
216222
"id" : "job id",
@@ -574,6 +580,24 @@ describe('functions', function() {
574580
});
575581
});
576582

583+
it('timeoutTest', function(done) {
584+
this.timeout(17000);
585+
request(AV.Cloud)
586+
.post('/1.1/functions/testTimeout')
587+
.set('X-AVOSCloud-Application-Id', appId)
588+
.set('X-AVOSCloud-Application-Key', appKey)
589+
.send({
590+
delay: 15200,
591+
})
592+
.expect(503)
593+
.end(function(err, res) {
594+
res.body.should.eql({code:124, error:"The request timed out on the server."});
595+
setTimeout(function() { // 等待业务逻辑真正响应,确认异常信息
596+
done();
597+
}, 1000);
598+
});
599+
});
600+
577601
// 用户串号测试
578602
it('user_matching_func', function(done) {
579603
this.timeout(30000);

0 commit comments

Comments
 (0)