rethinkdbdash
Version:
A Node.js driver for RethinkDB with promises and a connection pool
361 lines (323 loc) • 13 kB
JavaScript
var config = require(__dirname+'/config.js');
var r = require(__dirname+'/../lib')({pool: false, silent: true});
var util = require(__dirname+'/util/common.js');
var assert = require('assert');
var Promise = require('bluebird');
var uuid = util.uuid;
var It = util.It;
var uuid = util.uuid;
var dbName, tableName, result, pks;
var options = {
max: 10,
buffer: 2,
host: config.host,
port: config.port,
authKey: config.authKey,
discovery: false,
silent: true
};
It('`createPool` should create a PoolMaster and `getPoolMaster` should return it', function* (done) {
try {
r = r.createPools(options);
assert(r.getPoolMaster(config));
assert.equal(r.getPoolMaster().getPools().length, 1)
done();
}
catch(e) {
done(e);
}
});
//TODO try to make this tests a little more deterministic
It('`run` should work without a connection if a pool exists', function* (done) {
try {
result = yield r.expr(1).run()
assert.equal(result, 1);
done()
}
catch(e) {
done(e);
}
});
It('The pool should keep a buffer', function* (done) {
try {
result = yield [r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run()]
assert.deepEqual(result, [1,1,1,1,1]);
assert(r.getPool(0).getLength() >= options.buffer+result.length);
setTimeout( function() {
assert(r.getPool(0).getAvailableLength() >= result.length) // The connections created for the buffer may not be available yet
assert.equal(r.getPool(0).getLength(), r.getPool(0).getLength())
done();
}, 500)
}
catch(e) {
done(e);
}
});
It('A noreply query should release the connection', function* (done) {
try {
var numConnections = r.getPool(0).getLength();
yield r.expr(1).run({noreply: true})
assert.equal(r.getPool(0).getLength(), numConnections);
done();
}
catch(e) {
console.log(e)
done(e);
}
});
It('The pool should not have more than `options.max` connections', function* (done) {
try {
result = yield [r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run()]
assert.deepEqual(result, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
assert.equal(r.getPool(0).getLength(), options.max)
setTimeout( function() {
assert.equal(r.getPool(0).getAvailableLength(), options.max)
assert.equal(r.getPool(0).getAvailableLength(), r.getPool(0).getLength())
done()
}, 500)
}
catch(e) {
done(e);
}
});
It('Init for `pool.js`', function* (done) {
try {
dbName = uuid();
tableName = uuid();
result = yield r.dbCreate(dbName).run();
assert.equal(result.dbs_created, 1);
result = yield r.db(dbName).tableCreate(tableName).run();
assert.equal(result.tables_created, 1);
result = yield r.db(dbName).table(tableName).insert(eval('['+new Array(10000).join('{}, ')+'{}]')).run();
assert.equal(result.inserted, 10000);
pks = result.generated_keys;
done();
}
catch(e) {
done(e);
}
})
It('Updating data to make it heavier', function* (done) {
try {
//Making bigger documents to retrieve multiple batches
var result = yield r.db(dbName).table(tableName).update({
"foo": uuid(),
"fooo": uuid(),
"foooo": uuid(),
"fooooo": uuid(),
"foooooo": uuid(),
"fooooooo": uuid(),
"foooooooo": uuid(),
"fooooooooo": uuid(),
"foooooooooo": uuid(),
date: r.now()
}).run();
done();
}
catch(e) {
done(e);
}
})
It('The pool should release a connection only when the cursor has fetch everything or get closed', function* (done) {
try {
result = yield [r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true}),r.db(dbName).table(tableName).run({cursor: true})];
assert.equal(result.length, 10);
assert.equal(r.getPool(0).getAvailableLength(), 0);
yield result[0].toArray();
assert.equal(r.getPool(0).getAvailableLength(), 1);
yield result[1].toArray();
assert.equal(r.getPool(0).getAvailableLength(), 2);
yield result[2].close();
assert.equal(r.getPool(0).getAvailableLength(), 3);
yield [result[3].close(), result[4].close(), result[5].close(), result[6].close(), result[7].close(), result[8].close(), result[9].close()]
done();
}
catch(e) {
done(e);
}
});
It('The pool should shrink if a connection is not used for some time', function* (done) {
try{
r.getPool(0).setOptions({timeoutGb: 100});
result = yield [r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run()]
assert.deepEqual(result, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
setTimeout(function() {
assert.equal(r.getPool(0).getAvailableLength(), options.buffer)
assert.equal(r.getPool(0).getLength(), options.buffer)
done()
},400)
}
catch(e) {
done(e);
}
});
It('`poolMaster.drain` should eventually remove all the connections', function* (done) {
try{
yield r.getPoolMaster().drain();
assert.equal(r.getPool(0).getAvailableLength(), 0)
assert.equal(r.getPool(0).getLength(), 0)
done()
}
catch(e) {
done(e);
}
});
It('If the pool cannot create a connection, it should reject queries', function* (done) {
try {
var r = require(__dirname+'/../lib')({host: "notarealhost", buffer: 1, max: 2, silent: true});
yield r.expr(1).run()
done(new Error("Was expecting an error"));
}
catch(e) {
if (e.message === "None of the pools have an opened connection and failed to open a new one.") {
done()
}
else {
done(e);
}
}
});
It('If the pool cannot create a connection, it should reject queries - timeout', function* (done) {
try {
var r = require(__dirname+'/../lib')({host: "notarealhost", buffer: 1, max: 2, silent: true});
yield new Promise(function(resolve, reject) { setTimeout(resolve, 1000) });
yield r.expr(1).run()
done(new Error("Was expecting an error"));
}
catch(e) {
if (e.message === "None of the pools have an opened connection and failed to open a new one.") {
done()
}
else {
done(e);
}
}
});
It('If the pool is drained, it should reject queries - 1', function* (done) {
try {
var r = require(__dirname+'/../lib')({buffer: 1, max: 2, silent: true});
r.getPoolMaster().drain();
var result = yield r.expr(1).run();
done(new Error("Was expecting an error"));
}
catch(e) {
if (e.message === "None of the pools have an opened connection and failed to open a new one.") {
done()
}
else {
done(e);
}
}
});
It('If the pool is drained, it should reject queries - 2', function* (done) {
try {
var r = require(__dirname+'/../lib')({buffer: 1, max: 2, silent: true});
yield r.getPoolMaster().drain();
var result = yield r.expr(1).run();
done(new Error("Was expecting an error"));
}
catch(e) {
if (e.message === "None of the pools have an opened connection and failed to open a new one.") {
done()
}
else {
done(e);
}
}
});
It('`drain` should work in case of failures', function* (done) {
try {
r = r.createPools({
port: 80, // non valid port
silent: true,
timeoutError: 100
});
var pool = r.getPool(0);
// Sleep 1 sec
yield new Promise(function(resolve, reject) { setTimeout(resolve, 150) });
pool.drain();
// timeoutReconnect should have been canceled
assert.equal(pool.timeoutReconnect, null);
pool.options.silent = false;
yield new Promise(function(resolve, reject) { setTimeout(resolve, 1000) });
done();
}
catch(e) {
done(e);
}
});
/*
// This doesn't work anymore because since the JSON protocol was introduced.
It('The pool should remove a connection if it errored', function* (done) {
try{
r.getPool(0).setOptions({timeoutGb: 60*60*1000});
result = yield [r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run(), r.expr(1).run()]
assert.deepEqual(result, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
// This query will make the error return an error -1
result = yield r.expr(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1)
.run()
}
catch(e) {
if ((true) || (e.message === "Client is buggy (failed to deserialize protobuf)")) {
// We expect the connection that errored to get closed in the next second
setTimeout(function() {
assert.equal(r.getPool().getAvailableLength(), options.max-1)
assert.equal(r.getPool().getLength(), options.max-1)
done()
}, 1000)
}
else {
done(e);
}
}
});
*/