generic-pool
Advanced tools
Comparing version 2.2.2 to 2.3.0
@@ -60,2 +60,15 @@ var PriorityQueue = function(size) { | ||
function doWhileAsync( conditionFn, iterateFn, callbackFn ) { | ||
var next = function() { | ||
if ( conditionFn() ) { | ||
iterateFn( next ); | ||
} else { | ||
callbackFn(); | ||
} | ||
}; | ||
next(); | ||
} | ||
/** | ||
@@ -78,2 +91,8 @@ * Generate an Object pool with a specified `factory`. | ||
* acquired from pool. | ||
* @param {Function} factory.validateAsync | ||
* Asynchronous validate function. Receives a callback function | ||
* as its second argument, that should be called with a single | ||
* boolean argument being true if the item is still valid and false | ||
* if it should be removed from pool. Called before item is | ||
* acquired from pool. | ||
* @param {Number} factory.max | ||
@@ -131,10 +150,16 @@ * Maximum number of items that can exist at the same time. Default: 1. | ||
if ( factory.validate && factory.validateAsync ) { | ||
throw new Error( "Only one of validate or validateAsync may be specified" ); | ||
} | ||
factory.validate = factory.validate || function() { return true; }; | ||
factory.validateAsync = factory.validateAsync; | ||
factory.max = parseInt(factory.max, 10); | ||
factory.min = parseInt(factory.min, 10); | ||
factory.max = Math.max(isNaN(factory.max) ? 1 : factory.max, 1); | ||
factory.min = Math.min(isNaN(factory.min) ? 0 : factory.min, factory.max-1); | ||
/////////////// | ||
@@ -163,3 +188,3 @@ | ||
factory.destroy(obj); | ||
ensureMinimum(); | ||
@@ -188,3 +213,3 @@ }; | ||
toRemove.push(availableObjects[i].obj); | ||
} | ||
} | ||
} | ||
@@ -250,5 +275,32 @@ | ||
waitingCount = waitingClients.size(); | ||
log("dispense() clients=" + waitingCount + " available=" + availableObjects.length, 'info'); | ||
if (waitingCount > 0) { | ||
if ( factory.validateAsync ) { | ||
doWhileAsync( function() { | ||
return availableObjects.length > 0; | ||
}, function( next ) { | ||
log("dispense() - reusing obj", 'verbose'); | ||
objWithTimeout = availableObjects[0]; | ||
factory.validateAsync( objWithTimeout.obj, function( valid ) { | ||
if ( !valid ) { | ||
me.destroy(objWithTimeout.obj); | ||
next(); | ||
} else { | ||
availableObjects.shift(); | ||
clientCb = waitingClients.dequeue(); | ||
clientCb(err, objWithTimeout.obj); | ||
} | ||
} ) | ||
}, function() { | ||
if (count < factory.max) { | ||
createResource(); | ||
} | ||
} ); | ||
return; | ||
} | ||
while (availableObjects.length > 0) { | ||
@@ -271,3 +323,3 @@ log("dispense() - reusing obj", 'verbose'); | ||
} | ||
function createResource() { | ||
@@ -305,3 +357,3 @@ count += 1; | ||
} | ||
function ensureMinimum() { | ||
@@ -447,3 +499,3 @@ var i, diff; | ||
* @param {Function} decorated | ||
* The decorated function, accepting a client as the first argument and | ||
* The decorated function, accepting a client as the first argument and | ||
* (optionally) a callback as the final argument. | ||
@@ -476,3 +528,3 @@ * | ||
}); | ||
decorated.apply(null, args); | ||
@@ -479,0 +531,0 @@ }, priority); |
{ | ||
"name": "generic-pool", | ||
"description": "Generic resource pooling for Node.JS", | ||
"version": "2.2.2", | ||
"version": "2.3.0", | ||
"author": "James Cooper <james@bitmechanic.com>", | ||
@@ -14,3 +14,4 @@ "contributors": [ | ||
{ "name": "Justin Robinson", "email":"jrobinson@redventures.com>"}, | ||
{ "name": "Nayana Hettiarachchi", "email":"nayana@corp-gems.com"} | ||
{ "name": "Nayana Hettiarachchi", "email":"nayana@corp-gems.com"}, | ||
{ "name": "Felipe Machado", "email": "felipou@gmail.com"} | ||
], | ||
@@ -17,0 +18,0 @@ "keywords": ["pool", "pooling", "throttle"], |
@@ -7,18 +7,12 @@ [![build status](https://secure.travis-ci.org/coopernurse/node-pool.png)](http://travis-ci.org/coopernurse/node-pool) | ||
database connections. | ||
## 2.0 Release Warning | ||
The 2.0.0 release removed support for variable argument callbacks. When you acquire | ||
a resource from the pool, your callback *must* accept two arguments: (err, obj) | ||
Previously this library attempted to determine the arity of the callback, but this resulted | ||
in a variety of issues. This change eliminates these issues, and makes the acquire callback | ||
parameter order consistent with the factory.create callback. | ||
## Installation | ||
$ npm install generic-pool | ||
## History | ||
2.3.0 - January 1 2016 | ||
- Merged #105 - allow asynchronous validate functions (contributed by @felipou) | ||
2.2.2 - December 13 2015 | ||
@@ -37,3 +31,3 @@ - Merged #106 - fix condition where non "resource pool" created objects could be returned to the pool. (contributed by @devzer01) | ||
2.1.0 - June 19 2014 | ||
- Merged #72 - Add optional returnToHead flag, if true, resources are returned to head of queue (stack like | ||
- Merged #72 - Add optional returnToHead flag, if true, resources are returned to head of queue (stack like | ||
behaviour) upon release (contributed by calibr), also see #68 for further discussion. | ||
@@ -53,3 +47,3 @@ | ||
- Merged #53 - change the position of dispense and callback to ensure the time order (contributed by windyrobin) | ||
2.0.1 - August 29 2012 | ||
@@ -59,3 +53,3 @@ - Fix #44 - leak of 'err' and 'obj' in createResource() | ||
- Add travis-ci.org integration | ||
2.0.0 - July 31 2012 | ||
@@ -84,3 +78,3 @@ - Non-backwards compatible change: remove adjustCallback | ||
- Merged #21 (add getter methods to see pool size, etc. - contributed by BryanDonovan) | ||
1.0.7 - Oct 17 2011 | ||
@@ -91,10 +85,10 @@ - Merged #19 (prevent release on the same obj twice - contributed by tkrynski) | ||
1.0.6 - May 23 2011 | ||
- Merged #13 (support error variable in acquire callback - contributed by tmcw) | ||
- Merged #13 (support error variable in acquire callback - contributed by tmcw) | ||
- Note: This change is backwards compatible. But new code should use the two | ||
parameter callback format in pool.create() functions from now on. | ||
- Merged #15 (variable scope issue in dispense() - contributed by eevans) | ||
1.0.5 - Apr 20 2011 | ||
- Merged #12 (ability to drain pool - contributed by gdusbabek) | ||
1.0.4 - Jan 25 2011 | ||
@@ -113,4 +107,4 @@ - Fixed #6 (objects reaped with undefined timeouts) | ||
- Priority queueing enhancements | ||
1.0.2 - Nov 9 2010 | ||
1.0.2 - Nov 9 2010 | ||
- First NPM release | ||
@@ -135,3 +129,3 @@ | ||
c.connect(); | ||
// parameter order: err, resource | ||
@@ -144,7 +138,7 @@ // new in 1.0.6 | ||
// optional. if you set this, make sure to drain() (see step 3) | ||
min : 2, | ||
min : 2, | ||
// specifies how long a resource can stay idle in pool before being removed | ||
idleTimeoutMillis : 30000, | ||
// if true, logs via console.log - can also be a function | ||
log : true | ||
log : true | ||
}); | ||
@@ -173,6 +167,6 @@ ``` | ||
### Step 3 - Drain pool during shutdown (optional) | ||
If you are shutting down a long-lived process, you may notice | ||
that node fails to exit for 30 seconds or so. This is a side | ||
effect of the idleTimeoutMillis behavior -- the pool has a | ||
effect of the idleTimeoutMillis behavior -- the pool has a | ||
setTimeout() call registered that is in the event loop queue, so | ||
@@ -187,3 +181,3 @@ node won't terminate until all resources have timed out, and the pool | ||
In these cases, use the pool.drain() function. This sets the pool | ||
into a "draining" state which will gracefully wait until all | ||
into a "draining" state which will gracefully wait until all | ||
idle resources have timed out. For example, you can call: | ||
@@ -198,6 +192,6 @@ | ||
``` | ||
If you do this, your node process will exit gracefully. | ||
## Documentation | ||
@@ -229,4 +223,6 @@ | ||
is OK to use, or false if the object is invalid. Invalid objects will be destroyed. | ||
This function is called in acquire() before returning a resource from the pool. | ||
This function is called in acquire() before returning a resource from the pool. | ||
Optional. Default function always returns true. | ||
validateAsync : true/false - Indicates whether the validate function is | ||
asynchronous. Default is false. | ||
log : true/false or function - | ||
@@ -241,4 +237,4 @@ If a log is a function, it will be called with two parameters: | ||
The pool now supports optional priority queueing. This becomes relevant when no resources | ||
are available and the caller has to wait. `acquire()` accepts an optional priority int which | ||
The pool now supports optional priority queueing. This becomes relevant when no resources | ||
are available and the caller has to wait. `acquire()` accepts an optional priority int which | ||
specifies the caller's relative position in the queue. | ||
@@ -254,3 +250,3 @@ | ||
}, | ||
destroy : function(client) { | ||
destroy : function(client) { | ||
// cleanup. omitted for this example | ||
@@ -298,3 +294,3 @@ }, | ||
To transparently handle object acquisition for a function, | ||
To transparently handle object acquisition for a function, | ||
one can use `pooled()`: | ||
@@ -310,3 +306,3 @@ | ||
Keeping both private and public versions of each function allows for pooled | ||
Keeping both private and public versions of each function allows for pooled | ||
functions to call other pooled functions with the same member. This is a handy | ||
@@ -318,3 +314,3 @@ pattern for database transactions: | ||
publicBottom = pool.pooled(privateBottom = function(client, arg, cb) { | ||
//Use client, assumed auto-release | ||
//Use client, assumed auto-release | ||
}); | ||
@@ -359,7 +355,7 @@ | ||
## License | ||
## License | ||
(The MIT License) | ||
Copyright (c) 2010-2014 James Cooper <james@bitmechanic.com> | ||
Copyright (c) 2010-2016 James Cooper <james@bitmechanic.com> | ||
@@ -366,0 +362,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
@@ -10,3 +10,3 @@ var assert = require('assert'); | ||
var borrowCount = 0; | ||
var factory = { | ||
@@ -44,3 +44,3 @@ name : 'test1', | ||
}, | ||
'respects min limit' : function (beforeExit) { | ||
@@ -69,3 +69,3 @@ var createCount = 0; | ||
}, | ||
'min and max limit defaults' : function (beforeExit) { | ||
@@ -79,3 +79,3 @@ var factory = { | ||
var pool = poolModule.Pool(factory); | ||
beforeExit(function() { | ||
@@ -86,3 +86,3 @@ assert.equal(1, factory.max); | ||
}, | ||
'malformed min and max limits are ignored' : function (beforeExit) { | ||
@@ -98,3 +98,3 @@ var factory = { | ||
var pool = poolModule.Pool(factory); | ||
beforeExit(function() { | ||
@@ -105,3 +105,3 @@ assert.equal(1, factory.max); | ||
}, | ||
'min greater than max sets to max minus one' : function (beforeExit) { | ||
@@ -118,3 +118,3 @@ var factory = { | ||
pool.drain(); | ||
beforeExit(function() { | ||
@@ -344,6 +344,6 @@ assert.equal(3, factory.max); | ||
assert.equal(assertion_count, 4); | ||
assert.equal(destroyed_count, 1); | ||
assert.equal(destroyed_count, 1); | ||
}); | ||
}, | ||
'pooled decorator should pass arguments and return values' : function(beforeExit) { | ||
@@ -552,3 +552,3 @@ var assertion_count = 0; | ||
}, | ||
'removes from available objects on destroy': function(beforeExit){ | ||
@@ -566,6 +566,6 @@ var destroyCalled = false; | ||
pool.acquire(function(err, obj){ | ||
pool.destroy(obj); | ||
pool.destroy(obj); | ||
}); | ||
assert.equal(destroyCalled, true); | ||
assert.equal(pool.availableObjectsCount(), 0); | ||
assert.equal(pool.availableObjectsCount(), 0); | ||
}, | ||
@@ -601,2 +601,51 @@ | ||
'removes from available objects on async validation failure': function(beforeExit){ | ||
var destroyCalled = false, | ||
validateCalled = false, | ||
count = 0; | ||
var factory = { | ||
name: 'test', | ||
create: function(callback) {callback(null, {count: count++}); }, | ||
destroy: function(client) {destroyCalled = client.count; }, | ||
validateAsync: function(client, callback) {validateCalled = true; callback( client.count != 0 );}, | ||
max: 2, | ||
idleTimeoutMillis: 100 | ||
}; | ||
var pool = poolModule.Pool(factory); | ||
pool.acquire(function(err, obj){ | ||
pool.release(obj); | ||
assert.equal(obj.count, 0); | ||
pool.acquire(function(err, obj){ | ||
pool.release(obj); | ||
assert.equal(obj.count, 1); | ||
}); | ||
}); | ||
assert.equal(validateCalled, true); | ||
assert.equal(destroyCalled, 0); | ||
assert.equal(pool.availableObjectsCount(), 1); | ||
}, | ||
'error on setting both validate functions': function(beforeExit){ | ||
var destroyCalled = false, | ||
validateCalled = false, | ||
count = 0; | ||
var factory = { | ||
name: 'test', | ||
create: function(callback) {callback(null, {count: count++}); }, | ||
destroy: function(client) {destroyCalled = client.count; }, | ||
validate: function(client) {validateCalled = true; return client.count != 0; }, | ||
validateAsync: function(client, callback) {validateCalled = true; callback( client.count != 0 );}, | ||
max: 2, | ||
idleTimeoutMillis: 100 | ||
}; | ||
try { | ||
var pool = poolModule.Pool(factory); | ||
} catch ( err ) { | ||
assert.equal(err.message, "Only one of validate or validateAsync may be specified"); | ||
} | ||
}, | ||
'do schedule again if error occured when creating new Objects async': function(beforeExit){ | ||
@@ -608,3 +657,3 @@ var factory = { | ||
var err = new Error('Create Error'); | ||
callback(err); | ||
callback(err); | ||
}) | ||
@@ -623,7 +672,7 @@ }, | ||
assert(err); | ||
assert.equal(pool.availableObjectsCount(), 0); | ||
assert.equal(pool.availableObjectsCount(), 0); | ||
}); | ||
beforeExit(function() { | ||
assert.equal(getFlag, 1); | ||
assert.equal(getFlag, 1); | ||
}); | ||
@@ -630,0 +679,0 @@ }, |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
57148
1101
361