running all client integration tests against native client - many failures

This commit is contained in:
brianc 2011-03-03 18:21:43 +00:00
parent b6c3f7d478
commit 7e2f713af3
6 changed files with 157 additions and 158 deletions

141
lib/client-pool.js Normal file
View File

@ -0,0 +1,141 @@
var Pool = require(__dirname + '/utils').Pool;
var defaults = require(__dirname + '/defaults');
module.exports = {
init: function(Client) {
//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.removeListener('connect', 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.once('connect', 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.removeListener('connect', 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.once('connect', 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])
};
//export functions with closures to client constructor
return {
connect: connect,
end: end
}
}
};

View File

@ -1,142 +1,12 @@
var EventEmitter = require('events').EventEmitter;
var Pool = require(__dirname + '/utils').Pool;
var Client = require(__dirname+'/client');
var defaults = require(__dirname + '/defaults');
//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.removeListener('connect', 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.once('connect', 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])
}
var pool = require(__dirname + "/client-pool").init(Client);
module.exports = {
Client: Client,
Connection: require(__dirname + '/connection'),
connect: connect,
end: end,
connect: pool.connect,
end: pool.end,
defaults: defaults
}

View File

@ -105,17 +105,6 @@ var ctor = function(config) {
return connection;
};
var connect = function(config, callback) {
var client = new ctor(config);
client.connect();
client.on('connect', function() {
callback(null, client);
})
client.on('error', function(err) {
callback(err, null);
})
};
//event emitter proxy
var NativeQuery = function(text, values, callback) {
if(typeof text == 'object') {
@ -184,10 +173,10 @@ p._translateValues = function() {
}
}
var pool = require(__dirname + '/client-pool').init(ctor);
module.exports = {
Client: ctor,
connect: connect,
end: function() {
}
connect: pool.connect,
end: pool.end
};

View File

@ -3,6 +3,7 @@ var client = helper.client();
test("empty query message handling", function() {
client.query("");
assert.emits(client.connection, 'emptyQuery');
client.on('drain', client.end.bind(client));
assert.emits(client, 'drain', function() {
client.end.bind(client);
})
});

View File

@ -1,6 +1,8 @@
var helper = require(__dirname + '/../test-helper');
if(helper.args.native) {
Client = require(__dirname + '/../../lib/native').Client;
}
//export parent helper stuffs
module.exports = helper;
if(helper.args.verbose) {
}

View File

@ -9,11 +9,7 @@ var BufferList = require(__dirname+'/buffer-list')
var Connection = require('connection');
var args = require(__dirname + '/cli');
if(args.libpq) {
Client = require('binding').Client;
} else {
Client = require('client');
}
Client = require(__dirname + '/../lib').Client;
process.on('uncaughtException', function(d) {
if ('stack' in d && 'message' in d) {