forked from coopernurse/node-pool
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5fbfb91
Showing
6 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fabfile.pyc | ||
node-pool.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
|
||
# About | ||
|
||
Generic resource pool. Can be used to reuse or throttle expensive resources such as | ||
database connections. | ||
|
||
## Installation | ||
|
||
$ npm install pool | ||
|
||
## Example | ||
|
||
// Create a MySQL connection pool with | ||
// a max of 10 connections and a 30 second max idle time | ||
var poolModule = require('pool'); | ||
var pool = poolModule.Pool({ | ||
name : 'mysql', | ||
create : function(callback) { | ||
var Client = require('mysql').Client; | ||
var c = new Client(); | ||
c.user = 'scott'; | ||
c.password = 'tiger'; | ||
c.database = 'mydb'; | ||
c.connect(); | ||
callback(c); | ||
}, | ||
destroy : function(client) { client.end(); }, | ||
max : 10, | ||
idleTimeoutMillis : 30000 | ||
}); | ||
|
||
// borrow connection - callback function is called | ||
// once a resource becomes available | ||
pool.borrow(function(client) { | ||
client.query("select * from foo", [], function() { | ||
// return object back to pool | ||
pool.returnToPool(client); | ||
}); | ||
}); | ||
|
||
|
||
## Documentation | ||
|
||
// Pool() accepts 3 parameters: | ||
// | ||
// (a) factory object with 3 slots: | ||
// name: string name | ||
// create: function that returns a new resource | ||
// should call callback() with the created resource | ||
// destroy: function that accepts a resource and destroys it | ||
// | ||
// (b) max items to create in pool | ||
// (c) idle timeout (milliseconds) | ||
// | ||
|
||
## Run Tests | ||
|
||
$ npm install expresso | ||
$ expresso -I lib test/*.js | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# | ||
# dependencies: | ||
# fabric (apt-get install fabric) | ||
# node-jslint (http://github.com/reid/node-jslint) | ||
# expresso (or replace with whatever node.js test tool you're using) | ||
# | ||
|
||
from fabric.api import local | ||
import os, os.path | ||
|
||
def test(): | ||
local('expresso -I lib test/*', capture=False) | ||
|
||
def jslint(): | ||
ignore = [ "/lib-cov/" ] | ||
for root, subFolders, files in os.walk("."): | ||
for file in files: | ||
if file.endswith(".js"): | ||
filename = os.path.join(root,file) | ||
processFile = True | ||
for i in ignore: | ||
if filename.find(i) != -1: | ||
processFile = False | ||
if processFile: | ||
print filename | ||
local('jslint %s' % filename, capture=False) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
|
||
exports.Pool = function(factory) { | ||
var self = {}; | ||
|
||
var idleTimeoutMillis = factory.idleTimeoutMillis || 30000; | ||
var reapInterval = factory.reapInterval || 1000; | ||
|
||
var availableObjects = []; | ||
var objectTimeout = {}; | ||
var waitingClients = []; | ||
var obj; | ||
var count = 0; | ||
var removeIdleScheduled = false; | ||
|
||
function log(str) { | ||
//console.log("pool " + factory.name + " - " + str); | ||
} | ||
|
||
function removeIdle() { | ||
removeIdleScheduled = false; | ||
|
||
var toKeep = []; | ||
var now = new Date().getTime(); | ||
for (var i = 0; i < availableObjects.length; i++) { | ||
var timeout = objectTimeout[availableObjects[i]]; | ||
if (now < timeout) { | ||
toKeep.push(availableObjects[i]); | ||
} | ||
else { | ||
log("removeIdle() destroying obj - now:" + now + " timeout:" + timeout); | ||
self.destroy(availableObjects[i]); | ||
} | ||
} | ||
|
||
availableObjects = toKeep; | ||
|
||
if (availableObjects.length > 0) { | ||
log("availableObjects.length=" + availableObjects.length); | ||
scheduleRemoveIdle(); | ||
} | ||
else { | ||
log("removeIdle() all objects removed"); | ||
} | ||
} | ||
|
||
function scheduleRemoveIdle() { | ||
if (!removeIdleScheduled) { | ||
removeIdleScheduled = true; | ||
setTimeout(removeIdle, reapInterval); | ||
} | ||
} | ||
|
||
function dispense() { | ||
log("dispense() clients=" + waitingClients.length + " available=" + availableObjects.length); | ||
if (waitingClients.length > 0) { | ||
obj = null; | ||
if (availableObjects.length > 0) { | ||
log("dispense() - reusing obj"); | ||
obj = availableObjects.shift(); | ||
delete objectTimeout[obj]; | ||
waitingClients.shift()(obj); | ||
} | ||
else if (count < factory.max) { | ||
log("dispense() - creating obj - count="+count); | ||
factory.create(function(obj) { | ||
count++; | ||
if (waitingClients.length > 0) { | ||
waitingClients.shift()(obj); | ||
} | ||
else { | ||
self.returnToPool(obj); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
|
||
self.borrow = function(callback) { | ||
waitingClients.push(callback); | ||
dispense(); | ||
}; | ||
|
||
self.destroy = function(obj) { | ||
count--; | ||
factory.destroy(obj); | ||
}; | ||
|
||
self.returnToPool = function(obj) { | ||
//log("return to pool"); | ||
availableObjects.push(obj); | ||
objectTimeout[obj] = (new Date().getTime() + idleTimeoutMillis); | ||
log("timeout: " + objectTimeout[obj]); | ||
dispense(); | ||
scheduleRemoveIdle(); | ||
}; | ||
|
||
return self; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "pool", | ||
"description": "Generic resource pooling for Node.JS", | ||
"version": "1.0.0", | ||
"author": "James Cooper <james@bitmechanic.com>", | ||
"contributors": [ | ||
{ "name": "James Cooper", "email": "james@bitmechanic.com" } | ||
], | ||
"keywords": ["pool", "pooling", "throttle"], | ||
"main": "lib/pool.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "http://github.com/coopernurse/node-pool.git" | ||
}, | ||
"engines": { "node": ">= 0.2.0" } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
var poolModule = require('pool'); | ||
|
||
module.exports = { | ||
|
||
'expands to max limit' : function (assert, beforeExit) { | ||
var createCount = 0; | ||
var destroyCount = 0; | ||
|
||
var pool = poolModule.Pool({ | ||
name : 'test1', | ||
create : function(callback) { | ||
createCount++; | ||
callback(createCount); | ||
}, | ||
destroy : function(client) { destroyCount++; }, | ||
max : 2, | ||
idleTimeoutMillis : 100 | ||
}); | ||
|
||
for (var i = 0; i < 10; i++) { | ||
pool.borrow(function(obj) { | ||
setTimeout(function() { | ||
pool.returnToPool(obj); | ||
}, 100); | ||
}); | ||
} | ||
|
||
beforeExit(function() { | ||
assert.equal(2, createCount); | ||
assert.equal(2, destroyCount); | ||
}); | ||
} | ||
|
||
}; |