@@ -87,6 +87,7 @@ class ControlConnection extends events.EventEmitter {
8787 this . _addressTranslator = this . options . policies . addressResolution ;
8888 this . _reconnectionPolicy = this . options . policies . reconnection ;
8989 this . _reconnectionSchedule = this . _reconnectionPolicy . newSchedule ( ) ;
90+ this . _refreshInProgress = false ;
9091 this . _isShuttingDown = false ;
9192
9293 // Reference to the encoder of the last valid connection
@@ -216,7 +217,6 @@ class ControlConnection extends events.EventEmitter {
216217
217218 _setHealthListeners ( host , connection ) {
218219 const self = this ;
219- let wasRefreshCalled = 0 ;
220220
221221 function removeListeners ( ) {
222222 host . removeListener ( 'down' , downOrIgnoredHandler ) ;
@@ -225,11 +225,6 @@ class ControlConnection extends events.EventEmitter {
225225 }
226226
227227 function startReconnecting ( hostDown ) {
228- if ( wasRefreshCalled ++ !== 0 ) {
229- // Prevent multiple calls to reconnect
230- return ;
231- }
232-
233228 removeListeners ( ) ;
234229
235230 if ( self . _isShuttingDown ) {
@@ -446,13 +441,31 @@ class ControlConnection extends events.EventEmitter {
446441 }
447442
448443 /**
449- * Acquires a new connection and refreshes topology and keyspace metadata.
444+ * Acquires a new connection and refreshes topology and keyspace metadata, with protection against concurrent refreshes .
450445 * <p>When it fails obtaining a connection and there aren't any more hosts, it schedules reconnection.</p>
451446 * <p>When it fails obtaining the metadata, it marks connection and/or host unusable and retries using the same
452447 * iterator from query plan / host list</p>
453448 * @param {Iterator<Host> } [hostIterator]
454449 */
455450 async _refresh ( hostIterator ) {
451+ if ( this . _refreshInProgress ) {
452+ return ;
453+ }
454+ this . _refreshInProgress = true ;
455+
456+ try {
457+ return await this . _unsafeDoRefresh ( hostIterator )
458+ } finally {
459+ this . _refreshInProgress = false ;
460+ }
461+ }
462+
463+ /**
464+ * The actual implementation of the refresh logic, without protection against concurrent executions.
465+ * <p>Should only be used via _refresh.</p>
466+ * @param {Iterator<Host> } [hostIterator]
467+ */
468+ async _unsafeDoRefresh ( hostIterator ) {
456469 if ( this . _isShuttingDown ) {
457470 this . log ( 'info' , 'The ControlConnection will not be refreshed as the Client is being shutdown' ) ;
458471 return ;
@@ -499,7 +512,7 @@ class ControlConnection extends events.EventEmitter {
499512 }
500513
501514 // Retry the whole thing with the same query plan
502- return await this . _refresh ( hostIterator ) ;
515+ return await this . _unsafeDoRefresh ( hostIterator ) ;
503516 }
504517
505518 this . _reconnectionSchedule = this . _reconnectionPolicy . newSchedule ( ) ;
0 commit comments