Skip to content

Commit

Permalink
Merge pull request #74 from officert/feature/replica-sets
Browse files Browse the repository at this point in the history
Feature/replica sets
  • Loading branch information
officert committed Jan 7, 2016
2 parents 904ced4 + d4086c2 commit 17a8279
Show file tree
Hide file tree
Showing 30 changed files with 1,345 additions and 272 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- "4.2.0"
- "5.3.0"
services:
- mongodb
before_script:
Expand Down
11 changes: 6 additions & 5 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* =========================================================================
* Dependencies
* ========================================================================= */
'use strict';

const gulp = require('gulp');
const jshint = require('gulp-jshint');
const less = require('gulp-less');
Expand Down Expand Up @@ -221,8 +220,10 @@ gulp.task('serve-site', ['site-css'], () => {

gulp.task('default', ['serve']);

gulp.task('test', (next) => {
runSequence('jshint', 'test-int', 'test-unit', 'test-unit-ui', next);
gulp.task('test', () => {
runSequence('jshint', 'test-int', 'test-unit', 'test-unit-ui', () => {
process.exit(0);
});
});

gulp.task('test-int', () => {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"buffer": "3.6.0",
"csv": "0.4.6",
"jsonfile": "2.2.3",
"mongodb": "2.1.1",
"mongodb": "2.1.2",
"node-uuid": "1.4.7",
"path-extra": "3.0.0",
"tunnel-ssh": "3.0.0-alpha",
Expand All @@ -34,7 +34,7 @@
"jasmine-core": "2.4.1",
"jshint": "2.8.0",
"jshint-stylish": "2.1.0",
"karma": "0.13.15",
"karma": "0.13.19 ",
"karma-electron-launcher": "0.1.0",
"karma-jasmine": "0.3.6",
"karma-sinon": "1.0.4",
Expand Down
67 changes: 53 additions & 14 deletions src/lib/entities/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const util = require('util');
const uuid = require('node-uuid');
const _ = require('underscore');

const logger = require('lib/modules/logger');
const Database = require('lib/entities/database');
const errors = require('lib/errors');

Expand All @@ -20,8 +21,11 @@ class Connection {
*
* @param {Object} options
* @param {String} options.name
* @param {String} options.host
* @param {String} options.port
* @param {String} [options.host]
* @param {String} [options.port]
* @param {Object} [options.replicaSet]
* @param {String} [options.replicaSet.name]
* @param {Array<Object>} [options.replicaSet.sets]
*/
constructor(options) {
options = options || {};
Expand All @@ -31,6 +35,7 @@ class Connection {
_this.name = options.name;
_this.host = options.host;
_this.port = options.port;
_this.replicaSet = options.replicaSet;
_this.databases = [];

if (options.databaseName) {
Expand All @@ -42,37 +47,50 @@ class Connection {
auth: options.auth
};

if (options.auth) {
if (options.auth.username || options.auth.password) {
newDb.auth = {};
newDb.auth.username = options.auth.username;
newDb.auth.password = options.auth.password;
}
if (options.auth && (options.auth.username || options.auth.password)) {
newDb.auth = {};
newDb.auth.username = options.auth.username;
newDb.auth.password = options.auth.password;
}

_this.addDatabase(newDb);
}
}

get connectionString() {
if (!this._connectionString) {
this._connectionString = _getConnectionString(this);
}
return this._connectionString;
}

/**
* @method connect
*/
connect() {
var _this = this;

return new Promise((resolve, reject) => {
logger.log('Connecting to ' + _this.name + ' server @ ' + _this.connectionString + '...');

let client = new MongoClient();

let connectionString = _getConnectionString(_this);
if (!_this.connectionString) {
return reject(new Error('connecting does have a connection string'));
}

client.connect(connectionString, (err) => {
client.connect(_this.connectionString, (err, database) => {
if (err) return reject(new errors.ConnectionError(err.message));

logger.log('Connected to ' + _this.name + ' server @ ' + _this.connectionString);

if (_this.host === 'localhost') {
_getDbsForLocalhostConnection(_this, () => {
return resolve(null);
});
} else return resolve(null);
} else {
return resolve(database);
}
});
});
}
Expand Down Expand Up @@ -150,14 +168,35 @@ function _getConnectionString(connection) {
let db = (connection.databases && connection.databases.length) ? connection.databases[0] : null;
let auth = '';

if (db) {
auth = (db.auth && db.auth.username && db.auth.password) ? auth += (db.auth.username + ':' + db.auth.password + '@') : '';
if (db && db.auth && db.auth.username && db.auth.password) {
auth += (db.auth.username + ':' + db.auth.password + '@');
}

let connectionString = 'mongodb://' + auth + connection.host + ':' + connection.port;
let connectionString = 'mongodb://';
let hasReplSet = false;

if (connection && connection.replicaSet && connection.replicaSet.name && (connection.replicaSet.sets && connection.replicaSet.sets.length)) {
hasReplSet = true;

connectionString += auth;

for (let i = 0; i < connection.replicaSet.sets.length; i++) {
let set = connection.replicaSet.sets[i];

connectionString += set.host + ':' + set.port;

if (i < (connection.replicaSet.sets.length - 1)) {
connectionString += ',';
}
}
} else {
connectionString += auth + connection.host + ':' + connection.port;
}

if (db) connectionString += ('/' + db.name);

if (hasReplSet) connectionString += '?replicaSet=' + connection.replicaSet.name;

return connectionString;
}

Expand Down
72 changes: 44 additions & 28 deletions src/lib/entities/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const MongoDb = require('mongodb').Db;
const MongoServer = require('mongodb').Server;
const Promise = require('bluebird');

const Collection = require('lib/entities/collection');
const errors = require('lib/errors');
Expand All @@ -26,64 +27,80 @@ class Database {

var _this = this;
_this.id = options.id;
_this.name = options.name || 'test'; //TODO: validate name doesn't contain spaces
_this.host = options.host || 'localhost';
_this.port = options.port || 27017;
_this.auth = options.auth || null;
_this.name = options.name; //TODO: validate name doesn't contain spaces
_this.host = options.host;
_this.port = options.port;
_this.auth = options.auth;
_this.connection = options.connection;

_this.isOpen = false;

_this.collections = [];

_this._dbConnection = new MongoDb(_this.name, new MongoServer(_this.host, _this.port));
if (_this.host === 'localhost') {
_this._dbConnection = new MongoDb(_this.name, new MongoServer(_this.host, _this.port));
} else {
_this._dbConnection = null; //this is set by the parent connection once we've connect to it
}
}

/**
* @method open
* @param {Function} next - callback function
*/
open(next) {
open() {
var _this = this;

_this._dbConnection.open(function(err) {
if (err) return next(new errors.DatabaseError(err));

if (_this.auth && _this.auth.username && _this.auth.password) {
_this._dbConnection.authenticate(_this.auth.username, _this.auth.password, function(err) {
if (err) return next(new errors.DatabaseError(err.message));
return new Promise((resolve, reject) => {
//TODO: need to do some research and see if connecting to a database
//over and over like this is a performance issue or causes memory leaks
if (_this.host === 'localhost') {
_this._dbConnection.open((err) => {
if (err) return reject(new errors.DatabaseError(err.message));

return next(null);
return resolve(null);
});
} else {
return next(null);
_this.connection.connect()
.then((database) => {
if (!database) {
return reject(new Error('error connecting to database'));
} else {
_this._dbConnection = database;
}
return resolve(null);
})
.catch((err) => {
if (err) return reject(new errors.DatabaseError(err.message));
});
}
});
}

/**
* @method listCollections
* @param {Function} next - callback function
*/
listCollections(next) {
listCollections() {
var _this = this;

if (!_this.open) return next(new Error('Database is not open'));
return new Promise((resolve, reject) => {
if (!_this.open) return reject(new Error('Database is not open'));

if (_this.collections && _this.collections.length) {
return next(null, _this.collections);
}
if (_this.collections && _this.collections.length) {
return resolve(_this.collections);
}

_this._dbConnection.collections(function(err, collections) {
if (err) return next(new errors.DatabaseError(err));
_this._dbConnection.collections((err, collections) => {
if (err) return reject(new errors.DatabaseError(err.message));

_.each(collections, function(collection) {
_this.addCollection({
name: collection.collectionName
_.each(collections, (collection) => {
_this.addCollection({
name: collection.collectionName
});
});
});

return next(null, _this.collections);
return resolve(_this.collections);
});
});
}

Expand Down Expand Up @@ -127,7 +144,6 @@ class Database {
});
});
}

}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/lib/modules/connection/repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ function generateConnectionInstanceFromConfig(connectionConfig) {
id: connectionConfig.id || uuid.v4(),
name: connectionConfig.name,
host: connectionConfig.host,
port: connectionConfig.port
port: connectionConfig.port,
replicaSet: connectionConfig.replicaSet
});

_.each(connectionConfig.databases, (databaseConfig) => {
Expand Down Expand Up @@ -212,6 +213,7 @@ function convertConnectionInstanceIntoConfig(connection) {
name: connection.name,
host: connection.host,
port: connection.port,
replicaSet: connection.replicaSet,
databases: connection.databases ? connection.databases.map((database) => {
var db = {
id: database.id || uuid.v4(),
Expand Down
Loading

0 comments on commit 17a8279

Please sign in to comment.