From 3a8381db15f85f1a4d7021a84ff07b6b7faab9da Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Wed, 8 Feb 2023 10:05:30 +0100 Subject: [PATCH 1/3] fix(connection): disable createConnection buffering if autoCreate option is changed fix #12940 --- lib/model.js | 9 ++++++--- test/connection.test.js | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/model.js b/lib/model.js index 0269cb1fcfd..46b47cc42c8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1341,7 +1341,10 @@ Model.init = function init(callback) { this.schema.emit('init', this); - if (this.$init != null) { + const autoCreate = utils.getOption('autoCreate', + this.schema.options, this.db.config, this.db.base.options); + + if (this.$init != null && this.$autoCreate === autoCreate) { if (callback) { this.$init.then(() => callback(), err => callback(err)); return null; @@ -1349,11 +1352,11 @@ Model.init = function init(callback) { return this.$init; } + this.$autoCreate = autoCreate; + const Promise = PromiseProvider.get(); const autoIndex = utils.getOption('autoIndex', this.schema.options, this.db.config, this.db.base.options); - const autoCreate = utils.getOption('autoCreate', - this.schema.options, this.db.config, this.db.base.options); const _ensureIndexes = autoIndex ? cb => this.ensureIndexes({ _automatic: true }, cb) : diff --git a/test/connection.test.js b/test/connection.test.js index d27c7879605..71d44efb207 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -1526,4 +1526,23 @@ describe('connections:', function() { const connectionIds = m.connections.map(c => c.id); assert.deepEqual(connectionIds, [1, 2, 3, 4, 5]); }); + + it('with autoCreate = false after schema create (gh-12940)', async function() { + const m = new mongoose.Mongoose(); + + const schema = new Schema({ name: String }, { + collation: { locale: 'en_US', strength: 1 }, + collection: 'gh12940_Conn' + }); + const Model = m.model('gh12940_Conn', schema); + + await m.connect(start.uri, { + autoCreate: false + }); + + await Model.init(); + + const res = await m.connection.db.listCollections().toArray(); + assert.ok(!res.map(c => c.name).includes('gh12940_Conn')); + }); }); From afd06d5ca0ee7b67ae4fa897538129bedc398384 Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Mon, 20 Feb 2023 17:54:21 +0100 Subject: [PATCH 2/3] fix: adjusted createCollection call for concurrent initializations --- lib/model.js | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/model.js b/lib/model.js index d5d85e9d088..06f94374fc3 100644 --- a/lib/model.js +++ b/lib/model.js @@ -60,9 +60,11 @@ const modifiedPaths = require('./helpers/update/modifiedPaths'); const parallelLimit = require('./helpers/parallelLimit'); const parentPaths = require('./helpers/path/parentPaths'); const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline'); +const promiseOrCallback = require('./helpers/promiseOrCallback'); const pushNestedArrayPaths = require('./helpers/model/pushNestedArrayPaths'); const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField'); const setDottedPath = require('./helpers/path/setDottedPath'); +const STATES = require('./connectionstate'); const util = require('util'); const utils = require('./utils'); @@ -1341,10 +1343,7 @@ Model.init = function init(callback) { this.schema.emit('init', this); - const autoCreate = utils.getOption('autoCreate', - this.schema.options, this.db.config, this.db.base.options); - - if (this.$init != null && this.$autoCreate === autoCreate) { + if (this.$init != null) { if (callback) { this.$init.then(() => callback(), err => callback(err)); return null; @@ -1352,8 +1351,6 @@ Model.init = function init(callback) { return this.$init; } - this.$autoCreate = autoCreate; - const Promise = PromiseProvider.get(); const autoIndex = utils.getOption('autoIndex', this.schema.options, this.db.config, this.db.base.options); @@ -1361,9 +1358,33 @@ Model.init = function init(callback) { const _ensureIndexes = autoIndex ? cb => this.ensureIndexes({ _automatic: true }, cb) : cb => cb(); - const _createCollection = autoCreate ? - cb => this.createCollection({}, cb) : - cb => cb(); + + const model = this; + const _wrapCollHelper = function(fn) { + return function(cb) { + const conn = model.db; + + return promiseOrCallback(cb, cb => { + immediate(() => { + if ((conn.readyState === STATES.connecting || conn.readyState === STATES.disconnected) && conn._shouldBufferCommands()) { + conn._queue.push({ fn: fn, ctx: conn, args: [cb] }); + } else { + try { + fn.apply(conn, [cb]); + } catch (err) { + return cb(err); + } + } + }); + }); + }; + }; + const _createCollection = _wrapCollHelper(function _createCollection(cb) { + const autoCreate = utils.getOption('autoCreate', + model.schema.options, model.db.config, model.db.base.options); + if (autoCreate) model.createCollection({}, cb); + else cb(); + }); this.$init = new Promise((resolve, reject) => { _createCollection(error => { From 08b0efc757441a897551ec1040e644d6e20acdaf Mon Sep 17 00:00:00 2001 From: Luca Pizzini Date: Tue, 21 Feb 2023 11:20:31 +0100 Subject: [PATCH 3/3] fix: added autoIndex delayed check and removed _wrapCollHelper function --- lib/model.js | 50 ++++++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/lib/model.js b/lib/model.js index 0ec5dd3a585..a9f92b2f612 100644 --- a/lib/model.js +++ b/lib/model.js @@ -60,7 +60,6 @@ const modifiedPaths = require('./helpers/update/modifiedPaths'); const parallelLimit = require('./helpers/parallelLimit'); const parentPaths = require('./helpers/path/parentPaths'); const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline'); -const promiseOrCallback = require('./helpers/promiseOrCallback'); const pushNestedArrayPaths = require('./helpers/model/pushNestedArrayPaths'); const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField'); const setDottedPath = require('./helpers/path/setDottedPath'); @@ -1354,39 +1353,30 @@ Model.init = function init(callback) { } const Promise = PromiseProvider.get(); - const autoIndex = utils.getOption('autoIndex', - this.schema.options, this.db.config, this.db.base.options); - - const _ensureIndexes = autoIndex ? - cb => this.ensureIndexes({ _automatic: true }, cb) : - cb => cb(); const model = this; - const _wrapCollHelper = function(fn) { - return function(cb) { - const conn = model.db; - - return promiseOrCallback(cb, cb => { - immediate(() => { - if ((conn.readyState === STATES.connecting || conn.readyState === STATES.disconnected) && conn._shouldBufferCommands()) { - conn._queue.push({ fn: fn, ctx: conn, args: [cb] }); - } else { - try { - fn.apply(conn, [cb]); - } catch (err) { - return cb(err); - } - } - }); - }); - }; - }; - const _createCollection = _wrapCollHelper(function _createCollection(cb) { - const autoCreate = utils.getOption('autoCreate', + const _ensureIndexes = function(cb) { + const autoIndex = utils.getOption('autoIndex', model.schema.options, model.db.config, model.db.base.options); - if (autoCreate) model.createCollection({}, cb); + if (autoIndex) model.ensureIndexes({ _automatic: true }, cb); else cb(); - }); + }; + const _createCollection = function(cb) { + const conn = model.db; + + if ((conn.readyState === STATES.connecting || conn.readyState === STATES.disconnected) && conn._shouldBufferCommands()) { + conn._queue.push({ fn: _createCollection, ctx: conn, args: [cb] }); + } else { + try { + const autoCreate = utils.getOption('autoCreate', + model.schema.options, model.db.config, model.db.base.options); + if (autoCreate) model.createCollection({}, cb); + else cb(); + } catch (err) { + return cb(err); + } + } + }; this.$init = new Promise((resolve, reject) => { _createCollection(error => {