145 lines
3.3 KiB
JavaScript
145 lines
3.3 KiB
JavaScript
var EventEmitter = require('events').EventEmitter;
|
|
var sys = require('sys');
|
|
var net = require('net');
|
|
var Client = require(__dirname+'/client');
|
|
var defaults = require(__dirname + '/defaults');
|
|
var Pool = require(__dirname + '/utils').Pool;
|
|
|
|
//wrap up common connection management boilerplate
|
|
var connect = function(config, callback) {
|
|
if(poolEnabled()) {
|
|
return getPooledClient(config, callback)
|
|
}
|
|
|
|
var client = new Client(config);
|
|
client.connect();
|
|
|
|
var onError = function(error) {
|
|
client.connection.removeListener('readyForQuery', onReady);
|
|
callback(error);
|
|
}
|
|
|
|
var onReady = function() {
|
|
client.removeListener('error', onError);
|
|
callback(null, client);
|
|
client.on('drain', client.end.bind(client));
|
|
}
|
|
|
|
client.once('error', onError);
|
|
|
|
//TODO refactor
|
|
//i don't like reaching into the client's connection for attaching
|
|
//to specific events here
|
|
client.connection.once('readyForQuery', onReady);
|
|
}
|
|
|
|
|
|
//connection pool global cache
|
|
var clientPools = {
|
|
}
|
|
|
|
var poolEnabled = function() {
|
|
return defaults.poolSize;
|
|
}
|
|
|
|
var log = function() {
|
|
//do nothing
|
|
}
|
|
|
|
//for testing
|
|
// var log = function() {
|
|
// console.log.apply(console, arguments);
|
|
// }
|
|
|
|
var getPooledClient = function(config, callback) {
|
|
//lookup pool using config as key
|
|
//TODO this don't work so hot w/ object configs
|
|
var pool = clientPools[config];
|
|
|
|
//create pool if doesn't exist
|
|
if(!pool) {
|
|
//log("creating pool %s", config)
|
|
pool = clientPools[config] = new Pool(defaults.poolSize, function() {
|
|
//log("creating new client in pool %s", config)
|
|
var client = new Client(config);
|
|
client.connected = false;
|
|
return client;
|
|
})
|
|
}
|
|
|
|
pool.checkOut(function(err, client) {
|
|
|
|
//if client already connected just
|
|
//pass it along to the callback and return
|
|
if(client.connected) {
|
|
callback(null, client);
|
|
return;
|
|
}
|
|
|
|
var onError = function(error) {
|
|
client.connection.removeListener('readyForQuery', onReady);
|
|
callback(error);
|
|
pool.checkIn(client);
|
|
}
|
|
|
|
var onReady = function() {
|
|
client.removeListener('error', onError);
|
|
client.connected = true;
|
|
callback(null, client);
|
|
client.on('drain', function() {
|
|
pool.checkIn(client);
|
|
});
|
|
}
|
|
|
|
client.once('error', onError);
|
|
|
|
//TODO refactor
|
|
//i don't like reaching into the client's connection for attaching
|
|
//to specific events here
|
|
client.connection.once('readyForQuery', onReady);
|
|
|
|
client.connect();
|
|
|
|
});
|
|
}
|
|
|
|
//destroys the world
|
|
//or optionally only a single pool
|
|
//mostly used for testing or
|
|
//a hard shutdown
|
|
var end = function(name) {
|
|
if(!name) {
|
|
for(var poolName in clientPools) {
|
|
end(poolName)
|
|
return
|
|
}
|
|
}
|
|
var pool = clientPools[name];
|
|
//log("destroying pool %s", name);
|
|
pool.waits.forEach(function(wait) {
|
|
wait(new Error("Client is being destroyed"))
|
|
})
|
|
pool.waits = [];
|
|
pool.items.forEach(function(item) {
|
|
var client = item.ref;
|
|
if(client.activeQuery) {
|
|
//log("client is still active, waiting for it to complete");
|
|
client.on('drain', client.end.bind(client))
|
|
} else {
|
|
client.end();
|
|
}
|
|
})
|
|
//remove reference to pool lookup
|
|
clientPools[name] = null;
|
|
delete(clientPools[name])
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
Client: Client,
|
|
Connection: require(__dirname + '/connection'),
|
|
connect: connect,
|
|
end: end,
|
|
defaults: defaults
|
|
}
|