Skip to content

Instantly share code, notes, and snippets.

@ValYouW
Created July 3, 2017 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ValYouW/b93798390551fa4b8bffaaed427b60cb to your computer and use it in GitHub Desktop.
Save ValYouW/b93798390551fa4b8bffaaed427b60cb to your computer and use it in GitHub Desktop.
A mongoose connection manager
var config = require('core-api').config,
logger = require('core-api').logger.fork('api/storage/mongo'),
mongoose = require('mongoose');
// mongoose is using a polyfill - need to override it
mongoose.Promise = Promise;
var MONGO_OPTS = {
autoReconnect: true,
reconnectTries: 1e6
};
class DB {
constructor(config) {
// Validate config
if (!config || typeof config.host !== 'string' || !config.host || typeof config.db !== 'string' || !config.db) {
logger.error('Got invalid config object, missing host/db, got:', config);
throw new Error('Must get config with `host` and `db`');
}
config.port = config.port || 27017;
this.config = config;
this.db = config.db;
this.initialConnect = true; // First connect attempt is special
this.connection = null;
this.connect();
}
// <editor-fold desc="// Public Methods {...}">
get ready() {
return this.connection && this.connection.readyState === 1;
}
// </editor-fold> // Public Methods
// <editor-fold desc="// Private Methods {...}">
connect() {
var connStr = `mongodb://${this.config.host}:${this.config.port}/${this.db}`;
var opts = {server: MONGO_OPTS, user: this.config.user, pass: this.config.password};
logger.info('Connecting to mongo, connection string: `%s`, user: `%s`', connStr, this.config.user);
// Important to create only 1 connection instance as all Models will be created on it (as well as cmd buffering)
if (!this.connection) {
this.connection = mongoose.createConnection(connStr, opts);
this.registerConnectionEvents();
} else {
this.connection.open(connStr, opts);
}
}
registerConnectionEvents() {
// todo: Check whether add monitoring events: http://mongodb.github.io/node-mongodb-native/2.1/reference/management/sdam-monitoring/
// Emitted when connection.{open,openSet}() is executed on this connection
this.connection.on('connecting', this.handleConnectionEvent.bind(this, 'connecting', 'info'));
// Emitted when this connection successfully connects to the db. May be emitted multiple times in reconnected scenarios
this.connection.on('connected', this.handleConnectionEvent.bind(this, 'connected', 'info'));
// Emitted after we connected and onOpen is executed on all of this connections models
this.connection.on('open', this.handleConnectionEvent.bind(this, 'open', 'info'));
// Emitted when connection.close() was executed
this.connection.on('disconnecting', this.handleConnectionEvent.bind(this, 'disconnecting', 'warn'));
// Emitted after getting disconnected from the db
this.connection.on('disconnected', this.handleConnectionEvent.bind(this, 'disconnected', 'error'));
// Emitted after we disconnected and onClose executed on all of this connections models
this.connection.on('close', this.handleConnectionEvent.bind(this, 'close', 'warn'));
// Emitted after we connected and subsequently disconnected, followed by successfully another successful connection
this.connection.on('reconnected', this.handleConnectionEvent.bind(this, 'reconnected', 'info'));
// Emitted when an error occurs on this connection
this.connection.on('error', (err) => { this.handleError(err); });
}
handleConnectionEvent(ev, level) {
logger[level]('Mongo connection `%s`, db: %s', ev, this.db);
// Mongo driver will handle reconnect ONLY after we have made the initial connection, so till then need to manually reconnect
if (ev === 'disconnected' && this.initialConnect) {
logger.error('Mongo could not make initial connection to server, retry in 1 second');
setTimeout(() => this.connect(), 1000);
} else if (ev === 'open') {
this.initialConnect = false;
}
}
handleError(err) {
logger.error('Mongo connection got error, db: %s, err:', this.db, err);
}
// </editor-fold> // Private Methods
}
var dbInstances = new Map();
var Mongo = {};
module.exports = Mongo;
Mongo.Schema = mongoose.Schema;
Mongo.Types = mongoose.Types;
/**
* Gets a mongodb instance
* @param {string} db - The database name
* @returns {DB}
*/
Mongo.get = function(db) {
// If we have instance return it
var instance = dbInstances.get(db);
if (instance) {
return instance;
}
// Get this db config
var conf = config.get(`storage:mongo:${db}`);
if (!conf) {
throw new Error(`No mongo config found for db: ${db}`);
}
// Create a new DB and save it
instance = new DB(conf);
dbInstances.set(db, instance);
return instance;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment