Created
July 3, 2017 07:31
-
-
Save ValYouW/b93798390551fa4b8bffaaed427b60cb to your computer and use it in GitHub Desktop.
A mongoose connection manager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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