Test Plan: Pressed `?` on homepage. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D5761
96 lines
2.3 KiB
JavaScript
96 lines
2.3 KiB
JavaScript
/**
|
|
* @requires javelin-install
|
|
* javelin-util
|
|
* javelin-request
|
|
* @provides phabricator-shaped-request
|
|
* @javelin
|
|
*/
|
|
|
|
/**
|
|
* Send requests with rate limiting and retries, in response to some application
|
|
* trigger. This is used to implement comment previews in Differential and
|
|
* Maniphest.
|
|
*/
|
|
JX.install('PhabricatorShapedRequest', {
|
|
|
|
construct : function(uri, callback, data_callback) {
|
|
this._uri = uri;
|
|
this._callback = callback;
|
|
this._dataCallback = data_callback;
|
|
},
|
|
|
|
events : ['error'],
|
|
|
|
members : {
|
|
_callback : null,
|
|
_dataCallback : null,
|
|
_request : null,
|
|
_min : null,
|
|
_defer : null,
|
|
_last : null,
|
|
start : function() {
|
|
this.trigger();
|
|
},
|
|
|
|
trigger : function() {
|
|
|
|
clearTimeout(this._defer);
|
|
var data = this._dataCallback();
|
|
|
|
// Waiting on a request, rate-limit.
|
|
var waiting = (this._request);
|
|
|
|
// Just got a request back, rate-limit.
|
|
var recent = (this._min && (new Date().getTime() < this._min));
|
|
|
|
if (!waiting && !recent && this.shouldSendRequest(this._last, data)) {
|
|
this._last = data;
|
|
this._request = new JX.Request(this._uri, JX.bind(this, function(r) {
|
|
this._callback(r);
|
|
|
|
this._min = new Date().getTime() + this.getRateLimit();
|
|
clearTimeout(this._defer);
|
|
this._defer = setTimeout(
|
|
JX.bind(this, this.trigger),
|
|
this.getRateLimit()
|
|
);
|
|
}));
|
|
this._request.listen('error', JX.bind(this, function(error) {
|
|
this.invoke('error', error, this);
|
|
}));
|
|
this._request.listen('finally', JX.bind(this, function() {
|
|
this._request = null;
|
|
}));
|
|
this._request.setData(data);
|
|
this._request.setTimeout(this.getRequestTimeout());
|
|
this._request.send();
|
|
} else {
|
|
this._defer = setTimeout(
|
|
JX.bind(this, this.trigger),
|
|
this.getFrequency()
|
|
);
|
|
}
|
|
},
|
|
|
|
shouldSendRequest : function(last, data) {
|
|
if (last === null) {
|
|
return true;
|
|
}
|
|
|
|
for (var k in last) {
|
|
if (data[k] !== last[k]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
},
|
|
|
|
properties : {
|
|
rateLimit : 500,
|
|
frequency : 1000,
|
|
requestTimeout : 20000
|
|
}
|
|
});
|