diff --git a/lib/sql.js b/lib/sql.js index ae0515e..69aa88d 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -623,9 +623,22 @@ SQLConnector.prototype.execute = function(sql, params, options, callback) { const self = this; if (!this.dataSource.connected) { - return this.dataSource.once('connected', function() { - self.execute(sql, params, options, callback); - }); + // Prevent adding too many listeners to the 'connected' event on the datasource. + if (this.dataSource.listenerCount('connected') < + this.dataSource.getMaxOfflineRequests()) { + // allow this listener to be added to this event + return this.dataSource.once('connected', function() { + self.execute(sql, params, options, callback); + }); + } else { + const limitReachedError = new Error( + g.f( + 'Event listener limit reached. ' + + 'Increase maxOfflineRequests value in datasources.json.', + ), + ); + callback(limitReachedError); + } } const context = { req: { diff --git a/package.json b/package.json index a452d60..bb19507 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "chai-as-promised": "^7.1.1", "eslint": "^6.1.0", "eslint-config-loopback": "^13.1.0", - "loopback-datasource-juggler": "^3.12.0", + "loopback-datasource-juggler": "^3.32.0", "mocha": "^6.2.0" } } diff --git a/test/sql.test.js b/test/sql.test.js index a3119a3..a05dbd9 100644 --- a/test/sql.test.js +++ b/test/sql.test.js @@ -459,4 +459,40 @@ describe('sql connector', function() { done(err, results); }); }); + + it('should throw if the event listener limit is reached', function() { + ds.connected = false; + function runExecute() { + return connector.execute('SELECT * FROM `CUSTOMER`', function(err) { + throw err; + }); + } + + for (let i = 0; i < 16; i++) { + runExecute(); + } + + expect(function() { runExecute(); }).to.throw( + 'Event listener limit reached. ' + + 'Increase maxOfflineRequests value in datasources.json.', + ); + ds.connected = true; + ds.removeAllListeners(['connected']); + }); + + it('should not throw if the event listener limit is not reached', function() { + ds.connected = false; + function runExecute() { + return connector.execute('SELECT * FROM `CUSTOMER`', function(err) { + throw err; + }); + } + + for (let i = 0; i < 15; i++) { + runExecute(); + } + + expect(function() { runExecute(); }).to.not.throw(); + ds.connected = true; + }); });