73 lines
1.5 KiB
JavaScript
73 lines
1.5 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var RingBuffer = require('./ring_buffer');
|
||
|
|
||
|
var Functor = function(session, method) {
|
||
|
this._session = session;
|
||
|
this._method = method;
|
||
|
this._queue = new RingBuffer(Functor.QUEUE_SIZE);
|
||
|
this._stopped = false;
|
||
|
this.pending = 0;
|
||
|
};
|
||
|
|
||
|
Functor.QUEUE_SIZE = 8;
|
||
|
|
||
|
Functor.prototype.call = function(error, message, callback, context) {
|
||
|
if (this._stopped) return;
|
||
|
|
||
|
var record = { error: error, message: message, callback: callback, context: context, done: false },
|
||
|
called = false,
|
||
|
self = this;
|
||
|
|
||
|
this._queue.push(record);
|
||
|
|
||
|
if (record.error) {
|
||
|
record.done = true;
|
||
|
this._stop();
|
||
|
return this._flushQueue();
|
||
|
}
|
||
|
|
||
|
var handler = function(err, msg) {
|
||
|
if (!(called ^ (called = true))) return;
|
||
|
|
||
|
if (err) {
|
||
|
self._stop();
|
||
|
record.error = err;
|
||
|
record.message = null;
|
||
|
} else {
|
||
|
record.message = msg;
|
||
|
}
|
||
|
|
||
|
record.done = true;
|
||
|
self._flushQueue();
|
||
|
};
|
||
|
|
||
|
try {
|
||
|
this._session[this._method](message, handler);
|
||
|
} catch (err) {
|
||
|
handler(err);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Functor.prototype._stop = function() {
|
||
|
this.pending = this._queue.length;
|
||
|
this._stopped = true;
|
||
|
};
|
||
|
|
||
|
Functor.prototype._flushQueue = function() {
|
||
|
var queue = this._queue, record;
|
||
|
|
||
|
while (queue.length > 0 && queue.peek().done) {
|
||
|
record = queue.shift();
|
||
|
if (record.error) {
|
||
|
this.pending = 0;
|
||
|
queue.clear();
|
||
|
} else {
|
||
|
this.pending -= 1;
|
||
|
}
|
||
|
record.callback.call(record.context, record.error, record.message);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
module.exports = Functor;
|