"use strict";
/**
* Filter for timeout.
* Print a warn information when request timeout.
* @access private
*/
const logger = require('@sex-pomelo/sex-pomelo-logger').getLogger('pomelo', __filename);
const utils = require('../../util/utils');
const DEFAULT_TIMEOUT = 3000;
const DEFAULT_SIZE = 500;
module.exports = function(timeout, maxSize) {
return new FilterHandlerTimeout(timeout || DEFAULT_TIMEOUT, maxSize || DEFAULT_SIZE);
};
/** This filter is used for warning there is a timeout in handling a request.
* It will start a timer in its beforeFilter and clear it in its afterFilter.
* If afterFilter is called before the timer expiring, that means no timout occurs,
* the timer will be cleared in afterFilter. If the timer expires, but afterFilter is not yet called,
* that means a timeout occurs and a warning is thrown out and logged. The default timeout is 3 seconds,
* but you can configure it while loading it.
* <br/>
* 这个filter是用来对服务端处理超时进行警告的,在beforeFilter中会启动一个定时器,在afterFilter中清除。
* 如果在其定时器时间内,afterFilter被调用,定时器将会被清除,因此不会出现超时警告。
* 如果定时器超时时,afterFilter还没有执行到,则会引发超时警告,并记录日志。
* 默认的处理超时是3秒,可以在加载timeout的时候作为参数传入。
*
*
* @class
* @implements {Filter}
*/
let FilterHandlerTimeout = function(timeout, maxSize) {
this.timeout = timeout;
this.maxSize = maxSize;
this.timeouts = {};
this.curId = 0;
};
FilterHandlerTimeout.prototype.before = function(msg, session, next) {
let count = utils.size(this.timeouts);
if(count > this.maxSize) {
logger.warn('timeout filter is out of range, current size is %s, max size is %s', count, this.maxSize);
next();
return;
}
this.curId++;
this.timeouts[this.curId] = setTimeout(function() {
logger.error('request %j timeout.', msg.__route__);
}, this.timeout);
session.__timeout__ = this.curId;
next();
};
FilterHandlerTimeout.prototype.after = function(err, msg, session, resp, next) {
let timeout = this.timeouts[session.__timeout__];
if(timeout) {
clearTimeout(timeout);
delete this.timeouts[session.__timeout__];
}
next(err);
};