Pool object for use in connection pooling
This commit is contained in:
parent
f0a04a7e79
commit
169c6dc3ce
55
lib/utils.js
55
lib/utils.js
@ -9,3 +9,58 @@ if(typeof events.EventEmitter.prototype.once !== 'function') {
|
||||
});
|
||||
};
|
||||
}
|
||||
var Pool = function(maxSize, createFn) {
|
||||
this.maxSize = maxSize;
|
||||
this.createFn = createFn;
|
||||
this.items = [];
|
||||
this.waits = [];
|
||||
}
|
||||
|
||||
var p = Pool.prototype;
|
||||
|
||||
p.checkOut = function(callback) {
|
||||
var len = 0;
|
||||
for(var i = 0, len = this.items.length; i < len; i++) {
|
||||
var item = this.items[i];
|
||||
if(item.checkedIn) {
|
||||
return this._pulse(item, callback);
|
||||
}
|
||||
}
|
||||
//check if we can create a new item
|
||||
if(len < this.maxSize && this.createFn) {
|
||||
var item = {ref: this.createFn()}
|
||||
this.items.push(item);
|
||||
return this._pulse(item, callback)
|
||||
}
|
||||
this.waits.push(callback);
|
||||
return false; //did not execute sync
|
||||
}
|
||||
|
||||
p.checkIn = function(item) {
|
||||
//scan current items
|
||||
for(var i = 0, len = this.items.length; i < len; i++) {
|
||||
var currentItem = this.items[i];
|
||||
if(currentItem.ref == item) {
|
||||
currentItem.checkedIn = true;
|
||||
return this._pulse(currentItem);
|
||||
}
|
||||
}
|
||||
//add new item
|
||||
var newItem = {ref: item, checkedIn: true};
|
||||
this.items.push(newItem);
|
||||
return this._pulse(newItem);
|
||||
}
|
||||
|
||||
p._pulse = function(item, cb) {
|
||||
cb = cb || this.waits.pop()
|
||||
if(cb) {
|
||||
item.checkedIn = false;
|
||||
cb(null, item.ref)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Pool: Pool
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ assert.length = function(actual, expectedLength) {
|
||||
var expect = function(callback) {
|
||||
var executed = false;
|
||||
var id = setTimeout(function() {
|
||||
assert.ok(executed, "Expected execution never fired");
|
||||
assert.ok(executed, "Expected execution of " + callback + " fired");
|
||||
}, 1000)
|
||||
|
||||
return function(err, queryResult) {
|
||||
|
@ -1,10 +1,11 @@
|
||||
require(__dirname + '/test-helper');
|
||||
var Pool = require("utils").Pool;
|
||||
|
||||
//this tests the monkey patching
|
||||
//to ensure comptability with older
|
||||
//versions of node
|
||||
test("EventEmitter.once", function() {
|
||||
|
||||
|
||||
//an event emitter
|
||||
var stream = new MemoryStream();
|
||||
|
||||
@ -12,8 +13,80 @@ test("EventEmitter.once", function() {
|
||||
stream.once('single', function() {
|
||||
callCount++;
|
||||
});
|
||||
|
||||
|
||||
stream.emit('single');
|
||||
stream.emit('single');
|
||||
assert.equal(callCount, 1);
|
||||
});
|
||||
|
||||
test('an empty pool', function() {
|
||||
test('with no creation method', function() {
|
||||
var pool = new Pool(10);
|
||||
var brian = {name:'brian'};
|
||||
|
||||
test('can set and get an item', function() {
|
||||
pool.checkIn(brian);
|
||||
var sync = pool.checkOut(assert.calls(function(err, item) {
|
||||
assert.equal(brian, item)
|
||||
assert.same(brian, item)
|
||||
}))
|
||||
assert.ok(sync, "should have fired sync")
|
||||
})
|
||||
|
||||
test('checkout blocks until item checked back in', function() {
|
||||
var called = false;
|
||||
var sync = pool.checkOut(assert.calls(function(err, item) {
|
||||
called = true;
|
||||
assert.equal(brian, item)
|
||||
assert.same(brian, item)
|
||||
}))
|
||||
assert.ok(sync === false, "Should not have fired sync")
|
||||
assert.ok(called === false, "Should not have fired callback yet")
|
||||
pool.checkIn(brian)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
test('with a creation method', function() {
|
||||
var customName = "first";
|
||||
var callCount = 0;
|
||||
var pool = new Pool(3, function() {
|
||||
return {name: customName + (++callCount)};
|
||||
});
|
||||
|
||||
test('creates if pool is not at max size', function() {
|
||||
var sync = pool.checkOut(assert.calls(function(err, item) {
|
||||
assert.equal(item.name, "first1");
|
||||
}))
|
||||
assert.ok(sync, "Should have generated item & called callback in sync")
|
||||
})
|
||||
|
||||
test('creates again if item is checked out', function() {
|
||||
var sync = pool.checkOut(assert.calls(function(err, item) {
|
||||
assert.equal(item.name, "first2")
|
||||
}))
|
||||
assert.ok(sync, "Should have called in sync again")
|
||||
})
|
||||
var external = {name: 'boom'};
|
||||
test('can add another item', function() {
|
||||
pool.checkIn(external)
|
||||
var sync = pool.checkOut(assert.calls(function(err, item) {
|
||||
assert.equal(item.name, 'boom')
|
||||
}))
|
||||
assert.ok(sync, "Should have fired 3rd in sync")
|
||||
})
|
||||
|
||||
test('after pool is full, create is not called again', function() {
|
||||
var called = false;
|
||||
var sync = pool.checkOut(assert.calls(function(err, item) {
|
||||
called = true;
|
||||
assert.equal(item.name, 'boom')
|
||||
}))
|
||||
assert.ok(sync === false, "should not be sync")
|
||||
assert.ok(called === false, "should not have called callback")
|
||||
pool.checkIn(external);
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user