|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +const assert = require('assert'); |
| 4 | +const mongoose = require('mongoose'); |
| 5 | + |
| 6 | +/** |
| 7 | + * MongoDB storage interface |
| 8 | + * @constructor |
| 9 | + * @param {String} mongoURI |
| 10 | + * @param {Object} mongoOptions |
| 11 | + * @param {Object} storageOptions |
| 12 | + */ |
| 13 | +function Database(mongoURI, mongoOptions, storageOptions) { |
| 14 | + if (!(this instanceof Database)) { |
| 15 | + return new Database(mongoURI, mongoOptions, storageOptions); |
| 16 | + } |
| 17 | + |
| 18 | + assert(typeof mongoOptions === 'object', 'Invalid mongo options supplied'); |
| 19 | + |
| 20 | + this._uri = mongoURI; |
| 21 | + this._options = mongoOptions; |
| 22 | + this._log = (storageOptions && storageOptions.logger) || { |
| 23 | + info: console.log, |
| 24 | + debug: console.log, |
| 25 | + error: console.error, |
| 26 | + warn: console.warn, |
| 27 | + }; |
| 28 | + |
| 29 | + this._connect(); |
| 30 | +} |
| 31 | + |
| 32 | +Database.externalModels = require('storj-service-storage-models').models; |
| 33 | +Database.localModels = { |
| 34 | + Bucket: require('./bucket'), |
| 35 | + User: require('./user'), |
| 36 | +}; |
| 37 | +Database.constants = require('../constants'); |
| 38 | + |
| 39 | +/** |
| 40 | + * Connects to the database |
| 41 | + */ |
| 42 | +Database.prototype._connect = function () { |
| 43 | + const opts = Object.assign({ ssl: false }, this._options); |
| 44 | + |
| 45 | + if (opts.server) { |
| 46 | + this._log.warn( |
| 47 | + 'Deprecated \'server\' option detected in database configuration. ' + |
| 48 | + 'This option was removed in MongoDB driver 4.x and will be ignored. ' + |
| 49 | + 'Please remove it from your configuration.' |
| 50 | + ); |
| 51 | + delete opts.server; |
| 52 | + } |
| 53 | + |
| 54 | + this._log.info('opening database connection at %s', this._uri); |
| 55 | + |
| 56 | + this.connection = mongoose.createConnection(this._uri, opts); |
| 57 | + |
| 58 | + this.connection.on('error', (err) => { |
| 59 | + this._log.error('database connection error: %s', err.message); |
| 60 | + }); |
| 61 | + |
| 62 | + this.connection.on('disconnected', () => { |
| 63 | + this._log.warn('disconnected from database'); |
| 64 | + }); |
| 65 | + |
| 66 | + this.connection.on('connected', () => { |
| 67 | + this._log.info('connected to database'); |
| 68 | + }); |
| 69 | + |
| 70 | + this.models = this._createBoundModels(); |
| 71 | +}; |
| 72 | + |
| 73 | +/** |
| 74 | + * Return a dictionary of models bound to this connection |
| 75 | + */ |
| 76 | +Database.prototype._createBoundModels = function () { |
| 77 | + const bound = {}; |
| 78 | + |
| 79 | + const allModels = { |
| 80 | + ...Database.externalModels, |
| 81 | + ...Database.localModels, |
| 82 | + }; |
| 83 | + |
| 84 | + for (const model in allModels) { |
| 85 | + bound[model] = allModels[model](this.connection); |
| 86 | + } |
| 87 | + |
| 88 | + return bound; |
| 89 | +}; |
| 90 | + |
| 91 | +/** |
| 92 | + * Returns a promise that resolves when the connection is ready |
| 93 | + */ |
| 94 | +Database.prototype.ready = function () { |
| 95 | + return new Promise((resolve, reject) => { |
| 96 | + if (this.connection.readyState === 1) { |
| 97 | + return resolve(); |
| 98 | + } |
| 99 | + this.connection.once('connected', resolve); |
| 100 | + this.connection.once('error', reject); |
| 101 | + }); |
| 102 | +}; |
| 103 | + |
| 104 | +/** |
| 105 | + * Creates a Database instance from a config object |
| 106 | + * @param {Object} storageConfig - { mongoUrl, mongoOpts } |
| 107 | + * @param {Object} [logger] |
| 108 | + */ |
| 109 | +Database.createFromConfig = function (storageConfig, logger) { |
| 110 | + return new Database( |
| 111 | + storageConfig.mongoUrl, |
| 112 | + storageConfig.mongoOpts, |
| 113 | + logger ? { logger } : {} |
| 114 | + ); |
| 115 | +}; |
| 116 | + |
| 117 | +module.exports = Database; |
0 commit comments