You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
3.1 KiB
JavaScript
101 lines
3.1 KiB
JavaScript
9 years ago
|
'use strict';
|
||
|
|
||
|
var inherits = require('util').inherits,
|
||
|
EventEmitter = require('events').EventEmitter,
|
||
|
debug = require('debug')('pool2');
|
||
|
|
||
|
var _id = 0;
|
||
|
|
||
|
// this has promisey semantics but can't really be replaced with a simple promise
|
||
|
function ResourceRequest(timeout, callback) {
|
||
|
if (typeof timeout === 'function') {
|
||
|
callback = timeout;
|
||
|
timeout = Infinity;
|
||
|
}
|
||
|
if (typeof callback !== 'function') {
|
||
|
throw new Error('new ResourceRequest(): callback is required');
|
||
|
}
|
||
|
|
||
|
EventEmitter.call(this);
|
||
|
|
||
|
this.id = _id++;
|
||
|
this.ts = new Date();
|
||
|
this.cb = callback;
|
||
|
this.fulfilled = false;
|
||
|
this.timer = null;
|
||
|
|
||
|
debug('New ResourceRequest (id=%s, timeout=%s)', this.id, timeout);
|
||
|
|
||
|
if (timeout !== Infinity) { this.setTimeout(timeout); }
|
||
|
}
|
||
|
inherits(ResourceRequest, EventEmitter);
|
||
|
|
||
|
ResourceRequest.prototype.setTimeout = function (_duration) {
|
||
|
if (_duration === Infinity) {
|
||
|
debug('ResourceRequest: setTimeout called with Infinity: clearing timeout');
|
||
|
this.clearTimeout();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var duration = parseInt(_duration, 10);
|
||
|
|
||
|
if (isNaN(duration) || duration <= 0) {
|
||
|
throw new Error('ResourceRequest.setTimeout(): invalid duration: ' + duration);
|
||
|
}
|
||
|
|
||
|
var now = new Date(),
|
||
|
elapsed = now - this.ts;
|
||
|
|
||
|
if (elapsed > duration) {
|
||
|
setImmediate(this._rejectTimeout.bind(this));
|
||
|
} else {
|
||
|
this.timer = setTimeout(this._rejectTimeout.bind(this), duration - elapsed);
|
||
|
}
|
||
|
};
|
||
|
ResourceRequest.prototype.clearTimeout = function () {
|
||
|
debug('ResourceRequest: clearing timeout (id=%s)', this.id);
|
||
|
clearTimeout(this.timer);
|
||
|
this.timer = null;
|
||
|
};
|
||
|
ResourceRequest.prototype.resolve = function (res) {
|
||
|
debug('ResourceRequest: resolve (id=%s)', this.id);
|
||
|
this._fulfill(null, res);
|
||
|
};
|
||
|
ResourceRequest.prototype.reject = function (err) {
|
||
|
debug('ResourceRequest: reject (id=%s)', this.id);
|
||
|
this._fulfill(err);
|
||
|
};
|
||
|
ResourceRequest.prototype.abort = function (msg) {
|
||
|
msg = msg || 'No reason given';
|
||
|
|
||
|
debug('ResourceRequest: abort (id=%s)', this.id);
|
||
|
this.reject(new Error('ResourceRequest aborted: ' + msg));
|
||
|
};
|
||
|
ResourceRequest.prototype._rejectTimeout = function () {
|
||
|
debug('ResourceRequest: rejectTimeout (id=%s)', this.id);
|
||
|
this.reject(new Error('ResourceRequest timed out'));
|
||
|
};
|
||
|
ResourceRequest.prototype._fulfill = function (err, res) {
|
||
|
if (err !== null) {
|
||
|
debug('ResourceRequest: fulfilling with error: %s (id=%s)', err.message, this.id);
|
||
|
// ensure any error gets emitted
|
||
|
this.emit('error', err);
|
||
|
} else {
|
||
|
debug('ResourceRequest: fulfilling with resource (id=%s)', this.id);
|
||
|
}
|
||
|
|
||
|
// if we've already fulfilled this request, don't try to do it again
|
||
|
if (this.fulfilled) {
|
||
|
debug('ResourceRequest: redundant fulfill, not calling callback (id=%s)', this.id);
|
||
|
// but make sure somebody knows about it
|
||
|
this.emit('error', new Error('ResourceRequest already fulfilled'));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.fulfilled = true;
|
||
|
this.clearTimeout();
|
||
|
this.cb.apply(this, arguments);
|
||
|
};
|
||
|
|
||
|
module.exports = ResourceRequest;
|