diff --git a/lib/connection.js b/lib/connection.js index 8c02b686baa..6e52d6ca4a0 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -47,7 +47,8 @@ const noPasswordAuthMechanisms = [ * @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connection's models. * @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successful connection. * @event `error`: Emitted when an error occurs on this connection. - * @event `fullsetup`: Emitted after the driver has connected to primary and all secondaries if specified in the connection string. + * @event `operation-start`: Emitted when a call to the MongoDB Node.js driver, like a `find()` or `insertOne()`, happens on any collection tied to this connection. + * @event `operation-end`: Emitted when a call to the MongoDB Node.js driver, like a `find()` or `insertOne()`, either succeeds or errors. * @api public */ diff --git a/lib/drivers/node-mongodb-native/collection.js b/lib/drivers/node-mongodb-native/collection.js index e0a74c368d3..408da3d0e74 100644 --- a/lib/drivers/node-mongodb-native/collection.js +++ b/lib/drivers/node-mongodb-native/collection.js @@ -236,23 +236,30 @@ function iter(i) { } if (syncCollectionMethods[i] && typeof lastArg === 'function') { - const ret = collection[i].apply(collection, _args.slice(0, _args.length - 1)); - return lastArg.call(this, null, ret); + const result = collection[i].apply(collection, _args.slice(0, _args.length - 1)); + this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result }); + return lastArg.call(this, null, result); } const ret = collection[i].apply(collection, _args); if (ret != null && typeof ret.then === 'function') { return ret.then( - res => { - typeof lastArg === 'function' && lastArg(null, res); - return res; + result => { + if (typeof lastArg === 'function') { + lastArg(null, result); + } else { + this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, result }); + } + return result; }, - err => { + error => { if (typeof lastArg === 'function') { - lastArg(err); + lastArg(error); return; + } else { + this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error }); } - throw err; + throw error; } ); } diff --git a/test/connection.test.js b/test/connection.test.js index 77ec8ac64d1..4554436fca8 100644 --- a/test/connection.test.js +++ b/test/connection.test.js @@ -206,6 +206,56 @@ describe('connections:', function() { }); }); + describe('events', function() { + let conn; + + before(async function() { + conn = mongoose.createConnection(start.uri2); + await conn.asPromise(); + await conn.collection('test').deleteMany({}); + return conn; + }); + + after(function() { + return conn.close(); + }); + + it('operation-start', async function() { + const events = []; + conn.on('operation-start', ev => events.push(ev)); + + await conn.collection('test').findOne({ answer: 42 }); + assert.equal(events.length, 1); + assert.equal(events[0].collectionName, 'test'); + assert.equal(events[0].method, 'findOne'); + assert.deepStrictEqual(events[0].params, [{ answer: 42 }]); + + await conn.collection('test').insertOne({ _id: 12, answer: 99 }); + assert.equal(events.length, 2); + assert.equal(events[1].collectionName, 'test'); + assert.equal(events[1].method, 'insertOne'); + assert.deepStrictEqual(events[1].params, [{ _id: 12, answer: 99 }]); + }); + + it('operation-end', async function() { + const events = []; + conn.on('operation-end', ev => { + events.push(ev); + }); + + await conn.collection('test').insertOne({ _id: 17, answer: 42 }); + assert.equal(events.length, 1); + assert.equal(events[0].collectionName, 'test'); + assert.equal(events[0].method, 'insertOne'); + + await conn.collection('test').findOne({ answer: 42 }); + assert.equal(events.length, 2); + assert.equal(events[1].collectionName, 'test'); + assert.equal(events[1].method, 'findOne'); + assert.deepStrictEqual(events[1].result, { _id: 17, answer: 42 }); + }); + }); + it('should allow closing a closed connection', async function() { const db = mongoose.createConnection();