Skip to content

Commit c296f3a

Browse files
mbroadstdaprahamian
authored andcommitted
feat(eachAsync): dedupe async iteration with a common helper
1 parent 2d1ff40 commit c296f3a

File tree

2 files changed

+92
-70
lines changed

2 files changed

+92
-70
lines changed

lib/core/connection/pool.js

+59-69
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const apm = require('./apm');
1919
const Buffer = require('safe-buffer').Buffer;
2020
const connect = require('./connect');
2121
const updateSessionFromResponse = require('../sessions').updateSessionFromResponse;
22+
const eachAsync = require('../utils').eachAsync;
2223

2324
var DISCONNECTED = 'disconnected';
2425
var CONNECTING = 'connecting';
@@ -635,42 +636,35 @@ Pool.prototype.unref = function() {
635636

636637
// Destroy the connections
637638
function destroy(self, connections, options, callback) {
638-
let connectionCount = connections.length;
639-
function connectionDestroyed() {
640-
connectionCount--;
641-
if (connectionCount > 0) {
642-
return;
643-
}
644-
645-
// clear all pool state
646-
self.inUseConnections = [];
647-
self.availableConnections = [];
648-
self.connectingConnections = 0;
649-
self.executing = false;
650-
self.queue = [];
651-
self.reconnectConnection = null;
652-
self.numberOfConsecutiveTimeouts = 0;
653-
self.connectionIndex = 0;
654-
self.retriesLeft = self.options.reconnectTries;
655-
self.reconnectId = null;
656-
657-
// Set state to destroyed
658-
stateTransition(self, DESTROYED);
659-
if (typeof callback === 'function') {
660-
callback(null, null);
661-
}
662-
}
639+
eachAsync(
640+
connections,
641+
(conn, cb) => {
642+
CONNECTION_EVENTS.forEach(eventName => conn.removeAllListeners(eventName));
643+
conn.destroy(options, cb);
644+
},
645+
err => {
646+
if (err) {
647+
if (typeof callback === 'function') callback(err, null);
648+
return;
649+
}
663650

664-
if (connectionCount === 0) {
665-
connectionDestroyed();
666-
return;
667-
}
651+
// clear all pool state
652+
self.inUseConnections = [];
653+
self.availableConnections = [];
654+
self.connectingConnections = 0;
655+
self.executing = false;
656+
self.queue = [];
657+
self.reconnectConnection = null;
658+
self.numberOfConsecutiveTimeouts = 0;
659+
self.connectionIndex = 0;
660+
self.retriesLeft = self.options.reconnectTries;
661+
self.reconnectId = null;
668662

669-
// Destroy all connections
670-
connections.forEach(conn => {
671-
CONNECTION_EVENTS.forEach(eventName => conn.removeAllListeners(eventName));
672-
conn.destroy(options, connectionDestroyed);
673-
});
663+
// Set state to destroyed
664+
stateTransition(self, DESTROYED);
665+
if (typeof callback === 'function') callback(null, null);
666+
}
667+
);
674668
}
675669

676670
/**
@@ -755,43 +749,39 @@ Pool.prototype.destroy = function(force, callback) {
755749
*/
756750
Pool.prototype.reset = function(callback) {
757751
const connections = this.availableConnections.concat(this.inUseConnections);
758-
let connectionCount = connections.length;
759-
const connectionDestroyed = () => {
760-
connectionCount--;
761-
if (connectionCount > 0) {
762-
return;
763-
}
752+
eachAsync(
753+
connections,
754+
(conn, cb) => {
755+
CONNECTION_EVENTS.forEach(eventName => conn.removeAllListeners(eventName));
756+
conn.destroy({ force: true }, cb);
757+
},
758+
err => {
759+
if (err) {
760+
if (typeof callback === 'function') {
761+
callback(err, null);
762+
return;
763+
}
764+
}
764765

765-
// clear all pool state
766-
this.inUseConnections = [];
767-
this.availableConnections = [];
768-
this.connectingConnections = 0;
769-
this.executing = false;
770-
this.reconnectConnection = null;
771-
this.numberOfConsecutiveTimeouts = 0;
772-
this.connectionIndex = 0;
773-
this.retriesLeft = this.options.reconnectTries;
774-
this.reconnectId = null;
775-
776-
// create an initial connection, and kick off execution again
777-
_createConnection(this);
778-
779-
if (typeof callback === 'function') {
780-
callback(null, null);
766+
// clear all pool state
767+
this.inUseConnections = [];
768+
this.availableConnections = [];
769+
this.connectingConnections = 0;
770+
this.executing = false;
771+
this.reconnectConnection = null;
772+
this.numberOfConsecutiveTimeouts = 0;
773+
this.connectionIndex = 0;
774+
this.retriesLeft = this.options.reconnectTries;
775+
this.reconnectId = null;
776+
777+
// create an initial connection, and kick off execution again
778+
_createConnection(this);
779+
780+
if (typeof callback === 'function') {
781+
callback(null, null);
782+
}
781783
}
782-
};
783-
784-
// if we already have no connections, just reset state and callback
785-
if (connectionCount === 0) {
786-
connectionDestroyed();
787-
return;
788-
}
789-
790-
// destroy all connections
791-
connections.forEach(conn => {
792-
CONNECTION_EVENTS.forEach(eventName => conn.removeAllListeners(eventName));
793-
conn.destroy({ force: true }, connectionDestroyed);
794-
});
784+
);
795785
};
796786

797787
// Prepare the buffer that Pool.prototype.write() uses to send to the server

lib/core/utils.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,37 @@ function isPromiseLike(maybePromise) {
116116
return maybePromise && typeof maybePromise.then === 'function';
117117
}
118118

119+
/**
120+
* Applies the function `eachFn` to each item in `arr`, in parallel.
121+
*
122+
* @param {array} arr an array of items to asynchronusly iterate over
123+
* @param {function} eachFn A function to call on each item of the array. The callback signature is `(item, callback)`, where the callback indicates iteration is complete.
124+
* @param {function} callback The callback called after every item has been iterated
125+
*/
126+
function eachAsync(arr, eachFn, callback) {
127+
if (arr.length === 0) {
128+
callback(null);
129+
return;
130+
}
131+
132+
const length = arr.length;
133+
let completed = 0;
134+
function eachCallback(err) {
135+
if (err) {
136+
callback(err, null);
137+
return;
138+
}
139+
140+
if (++completed === length) {
141+
callback(null);
142+
}
143+
}
144+
145+
for (let idx = 0; idx < length; ++idx) {
146+
eachFn(arr[idx], eachCallback);
147+
}
148+
}
149+
119150
module.exports = {
120151
uuidV4,
121152
calculateDurationInMs,
@@ -124,5 +155,6 @@ module.exports = {
124155
retrieveEJSON,
125156
retrieveKerberos,
126157
maxWireVersion,
127-
isPromiseLike
158+
isPromiseLike,
159+
eachAsync
128160
};

0 commit comments

Comments
 (0)