Skip to content

Commit

Permalink
Merge pull request #12130 from Automattic/vkarpov15/gh-12047
Browse files Browse the repository at this point in the history
fix(connection): re-run `Model.init()` if re-connecting after explicitly closing a connection
  • Loading branch information
vkarpov15 committed Jul 26, 2022
2 parents f62cf52 + 9661958 commit 47c3231
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
21 changes: 19 additions & 2 deletions lib/connection.js
Expand Up @@ -553,8 +553,8 @@ Connection.prototype.dropDatabase = _wrapConnHelper(function dropDatabase(cb) {
// init-ed. It is sufficiently common to call `dropDatabase()` after
// `mongoose.connect()` but before creating models that we want to
// support this. See gh-6796
for (const name of Object.keys(this.models)) {
delete this.models[name].$init;
for (const model of Object.values(this.models)) {
delete model.$init;
}
this.db.dropDatabase(cb);
});
Expand Down Expand Up @@ -841,6 +841,11 @@ Connection.prototype.openUri = function(uri, options, callback) {
);
}

for (const model of Object.values(this.models)) {
// Errors handled internally, so safe to ignore error
model.init(function $modelInitNoop() {});
}

return this.$initialConnection;
};

Expand Down Expand Up @@ -954,6 +959,13 @@ Connection.prototype.close = function(force, callback) {
this.$wasForceClosed = !!force;
}

for (const model of Object.values(this.models)) {
// If manually disconnecting, make sure to clear each model's `$init`
// promise, so Mongoose knows to re-run `init()` in case the
// connection is re-opened. See gh-12047.
delete model.$init;
}

return promiseOrCallback(callback, cb => {
this._close(force, false, cb);
});
Expand Down Expand Up @@ -1446,6 +1458,11 @@ Connection.prototype.setClient = function setClient(client) {
this._connectionString = client.s.url;
_setClient(this, client, {}, client.s.options.dbName);

for (const model of Object.values(this.models)) {
// Errors handled internally, so safe to ignore error
model.init(function $modelInitNoop() {});
}

return this;
};

Expand Down
66 changes: 66 additions & 0 deletions test/connection.test.js
Expand Up @@ -1135,6 +1135,72 @@ describe('connections:', function() {
assert.deepStrictEqual(conn3.id, m.connection.id + 2);
});

describe('Automatic init', function() {
it('re-runs init() if connecting after disconnecting (gh-12047)', async function() {
const conn = await mongoose.createConnection(start.uri).asPromise();

const Test = conn.model('Test', new Schema({ name: { type: String, index: true } }));
await Test.init();

let indexes = await Test.collection.listIndexes().toArray();
assert.equal(indexes.length, 2);
assert.equal(indexes[1].name, 'name_1');

await conn.db.dropCollection(Test.collection.collectionName);

const err = await Test.collection.listIndexes().toArray().then(() => null, err => err);
assert.ok(err);
assert.equal(err.codeName, 'NamespaceNotFound');

await conn.close();

await conn.openUri(start.uri);
assert.ok(Test.$init);
await Test.init();

indexes = await Test.collection.listIndexes().toArray();
assert.equal(indexes.length, 2);
assert.equal(indexes[1].name, 'name_1');
});

it('re-runs init() if running setClient() after disconnecting (gh-12047)', async function() {
const conn = await mongoose.createConnection(start.uri).asPromise();

const Test = conn.model('Test', new Schema({ name: { type: String, index: true } }));
await Test.init();

let indexes = await Test.collection.listIndexes().toArray();
assert.equal(indexes.length, 2);
assert.equal(indexes[1].name, 'name_1');

await conn.db.dropCollection(Test.collection.collectionName);

const err = await Test.collection.listIndexes().toArray().then(() => null, err => err);
assert.ok(err);
assert.equal(err.codeName, 'NamespaceNotFound');

await conn.close();

const client = await mongodb.MongoClient.connect(start.uri);

try {
conn.setClient(client);
assert.ok(Test.$init);
await Test.init();

indexes = await Test.collection.listIndexes().toArray();
assert.equal(indexes.length, 2);
assert.equal(indexes[1].name, 'name_1');

await client.close();
} catch (err) {
await client.close().catch(() => {});

throw err;
}
});
});

describe('Connection#syncIndexes() (gh-10893) (gh-11039)', () => {
let connection;
this.beforeEach(async() => {
Expand Down

0 comments on commit 47c3231

Please sign in to comment.