pooled-pg
Version:
A driver to PostgreSQL that is compatible with pg, with more effective pooling strategies.
164 lines (144 loc) • 2.86 kB
JavaScript
;
/**
* A pooled connection to PostgreSQL using pg.
* (C) 2015 Alex Fernández.
*/
// requires
var pg = require('pg');
var Log = require('log');
var testing = require('testing');
var genericPool = require('generic-pool');
var defaults = require('./defaults.js');
// globals
var log = new Log('info');
var clients = {};
exports.setLogLevel = function(level)
{
log = new Log(level);
};
exports.pooledConnect = function(address, callback)
{
var client = getClient(address);
callback(null, client, client.done);
};
function getClient(address)
{
if (!clients[address])
{
clients[address] = new exports.PooledClient(address);
}
return clients[address];
}
exports.end = function()
{
for (var address in clients)
{
clients[address].end();
}
pg.end();
};
exports.PooledClient = function(address)
{
// self-reference
var self = this;
// attributes
var pool = createPool(address);
self.query = function(query, params, callback)
{
if (typeof params == 'function')
{
callback = params;
params = null;
}
if (address == 'test')
{
return callback(null, {
rowCount: 1,
rows: [{"current_user":"test"}],
});
}
pool.acquire(function(error, client)
{
if (error)
{
return callback('Could not connect to ' + address + ': ' + error);
}
client.query(query, params, function(error, result)
{
pool.release(client);
if (error)
{
return callback('Could not run query ' + query + ': ' + error);
}
return callback(null, result);
});
});
};
self.done = function()
{
};
self.end = function()
{
pool.drain(function()
{
pool.destroyAllNow();
});
};
};
function createPool(address)
{
var pool = genericPool.Pool({
name: 'postgres',
create: function(callback)
{
log.debug('Creating client to %s', address);
var client = new pg.Client(address);
client.connect(function(error)
{
if (error)
{
return callback(error);
}
client.on('error', function(error)
{
log.error('Error in client, removing from pool: %s', error);
pool.destroy(client);
});
callback(null, client);
});
},
destroy: function(client)
{
log.debug('Destroying client to %s', address);
client.end();
},
max: defaults.poolSize,
idleTimeoutMillis : defaults.poolIdleTimeout,
});
return pool;
}
function testPooledClient(callback)
{
var client = new exports.PooledClient('test');
client.query('select current_user', function(error)
{
testing.check(error, 'Could not run query to test', callback);
client.end();
testing.success(callback);
});
}
/**
* Run package tests.
*/
exports.test = function(callback)
{
var tests = [
testPooledClient,
];
testing.run(tests, callback);
};
// run tests if invoked directly
if (__filename == process.argv[1])
{
exports.test(testing.show);
}