@@ -20,7 +20,6 @@ const MAX_CONNECTION_NAME_LENGTH = 512;
2020export enum DataServiceEventTypes {
2121 CONNECTIONS_DID_CHANGE = 'CONNECTIONS_DID_CHANGE' ,
2222 ACTIVE_CONNECTION_CHANGED = 'ACTIVE_CONNECTION_CHANGED' ,
23- ACTIVE_CONNECTION_CHANGING = 'ACTIVE_CONNECTION_CHANGING'
2423}
2524
2625export enum ConnectionTypes {
@@ -55,6 +54,12 @@ export default class ConnectionController {
5554 _activeConnectionModel : null | ConnectionModelType = null ;
5655 private _currentConnectionId : null | string = null ;
5756
57+ // When we are connecting to a server we save a connection version to
58+ // the request. That way if a new connection attempt is made while
59+ // the connection is being established, we know we can ignore the
60+ // request when it is completed so we don't have two live connections at once.
61+ private _connectingVersion = 0 ;
62+
5863 private _connecting = false ;
5964 private _connectingConnectionId : null | string = null ;
6065 private _disconnecting = false ;
@@ -231,32 +236,24 @@ export default class ConnectionController {
231236 public sendTelemetry (
232237 newDataService : DataServiceType ,
233238 connectionType : ConnectionTypes
234- ) {
239+ ) : void {
235240 // Send metrics to Segment
236241 this . _telemetryController . trackNewConnection (
237242 newDataService ,
238243 connectionType
239244 ) ;
240245 }
241246
242- public parseNewConnectionAndConnect = (
247+ public parseNewConnection = (
243248 newConnectionModel : ConnectionModelType
244- ) : Promise < boolean > => {
249+ ) : ConnectionModelType => {
245250 // Here we re-parse the connection, as it can be loaded from storage or
246251 // passed by the connection model without the class methods.
247- let connectionModel : ConnectionModelType ;
248-
249- try {
250- connectionModel = new Connection ( newConnectionModel ) ;
251- } catch ( error ) {
252- vscode . window . showErrorMessage ( `Unable to load connection: ${ error } ` ) ;
253- return Promise . reject ( new Error ( `Unable to load connection: ${ error } ` ) ) ;
254- }
255-
256- return this . saveNewConnectionAndConnect (
257- connectionModel ,
258- ConnectionTypes . CONNECTION_FORM
252+ const connectionModel : ConnectionModelType = new Connection (
253+ newConnectionModel
259254 ) ;
255+
256+ return connectionModel ;
260257 } ;
261258
262259 public saveNewConnectionAndConnect = async (
@@ -330,27 +327,19 @@ export default class ConnectionController {
330327 } ) . instanceId
331328 ) ;
332329
333- if ( this . _connecting ) {
334- return Promise . reject (
335- new Error ( 'Unable to connect: already connecting.' )
336- ) ;
337- }
338-
339- if ( this . _disconnecting ) {
340- return Promise . reject (
341- new Error ( 'Unable to connect: currently disconnecting.' )
342- ) ;
343- }
344-
345- if ( this . _activeDataService ) {
346- await this . disconnect ( ) ;
347- }
330+ // Store a version of this connection, so we can see when the conection
331+ // is successful if it is still the most recent connection attempt.
332+ this . _connectingVersion ++ ;
333+ const connectingAttemptVersion = this . _connectingVersion ;
348334
349335 this . _connecting = true ;
350336 this . _connectingConnectionId = connectionId ;
351337
352338 this . eventEmitter . emit ( DataServiceEventTypes . CONNECTIONS_DID_CHANGE ) ;
353- this . eventEmitter . emit ( DataServiceEventTypes . ACTIVE_CONNECTION_CHANGING ) ;
339+
340+ if ( this . _activeDataService ) {
341+ await this . disconnect ( ) ;
342+ }
354343
355344 this . _statusView . showMessage ( 'Connecting to MongoDB...' ) ;
356345
@@ -361,6 +350,22 @@ export default class ConnectionController {
361350 const newDataService : DataServiceType = new DataService ( connectionModel ) ;
362351
363352 newDataService . connect ( ( err : Error | undefined ) => {
353+ if (
354+ connectingAttemptVersion !== this . _connectingVersion ||
355+ ! this . _connections [ connectionId ]
356+ ) {
357+ // If the current attempt is no longer the most recent attempt
358+ // or the connection no longer exists we silently end the connection
359+ // and return.
360+ try {
361+ newDataService . disconnect ( ( ) => { } ) ;
362+ } catch ( e ) {
363+ /* */
364+ }
365+
366+ return resolve ( false ) ;
367+ }
368+
364369 this . _statusView . hideMessage ( ) ;
365370
366371 if ( err ) {
@@ -392,7 +397,7 @@ export default class ConnectionController {
392397
393398 public connectWithConnectionId = ( connectionId : string ) : Promise < boolean > => {
394399 if ( this . _connections [ connectionId ] ) {
395- let connectionModel : any ;
400+ let connectionModel : ConnectionModelType ;
396401
397402 try {
398403 const savedConnectionModel = this . _connections [ connectionId ]
@@ -433,36 +438,28 @@ export default class ConnectionController {
433438 this . _currentConnectionId
434439 ) ;
435440
436- if ( this . _disconnecting ) {
441+ if ( ! this . _activeDataService ) {
437442 vscode . window . showErrorMessage (
438- 'Unable to disconnect: already disconnecting from an instance .'
443+ 'Unable to disconnect: no active connection .'
439444 ) ;
440445
441446 return Promise . resolve ( false ) ;
442447 }
443448
444- if ( this . _connecting ) {
445- // TODO: The desired UX here may be for the connection to be interrupted.
446- vscode . window . showErrorMessage (
447- 'Unable to disconnect: currently connecting to an instance.'
448- ) ;
449+ const dataServiceToDisconnectFrom = this . _activeDataService ;
449450
450- return Promise . resolve ( false ) ;
451- }
451+ this . _activeDataService = null ;
452+ this . _currentConnectionId = null ;
453+ this . _activeConnectionModel = null ;
454+ this . _disconnecting = true ;
455+
456+ this . eventEmitter . emit ( DataServiceEventTypes . CONNECTIONS_DID_CHANGE ) ;
457+ this . eventEmitter . emit ( DataServiceEventTypes . ACTIVE_CONNECTION_CHANGED ) ;
452458
453459 // Disconnect from the active connection.
454460 return new Promise < boolean > ( ( resolve ) => {
455- if ( ! this . _activeDataService ) {
456- vscode . window . showErrorMessage (
457- 'Unable to disconnect: no active connection.'
458- ) ;
459-
460- return resolve ( false ) ;
461- }
462-
463- this . _disconnecting = true ;
464461 this . _statusView . showMessage ( 'Disconnecting from current connection...' ) ;
465- this . _activeDataService . disconnect ( ( err : Error | undefined ) : void => {
462+ dataServiceToDisconnectFrom . disconnect ( ( err : Error | undefined ) : void => {
466463 if ( err ) {
467464 // Show an error, however we still reset the active connection to free up the extension.
468465 vscode . window . showErrorMessage (
@@ -471,17 +468,9 @@ export default class ConnectionController {
471468 } else {
472469 vscode . window . showInformationMessage ( 'MongoDB disconnected.' ) ;
473470 }
474-
475- this . _activeDataService = null ;
476- this . _currentConnectionId = null ;
477- this . _activeConnectionModel = null ;
478-
479471 this . _disconnecting = false ;
480472 this . _statusView . hideMessage ( ) ;
481473
482- this . eventEmitter . emit ( DataServiceEventTypes . CONNECTIONS_DID_CHANGE ) ;
483- this . eventEmitter . emit ( DataServiceEventTypes . ACTIVE_CONNECTION_CHANGED ) ;
484-
485474 return resolve ( true ) ;
486475 } ) ;
487476 } ) ;
@@ -506,24 +495,6 @@ export default class ConnectionController {
506495
507496 // Prompts the user to remove the connection then removes it on affirmation.
508497 public async removeMongoDBConnection ( connectionId : string ) : Promise < boolean > {
509- // Ensure we aren't currently connecting.
510- if ( this . _connecting ) {
511- vscode . window . showErrorMessage (
512- 'Unable to remove connection: currently connecting.'
513- ) ;
514-
515- return Promise . resolve ( false ) ;
516- }
517-
518- // Ensure we aren't currently disconnecting.
519- if ( this . _disconnecting ) {
520- vscode . window . showErrorMessage (
521- 'Unable to remove connection: currently disconnecting.'
522- ) ;
523-
524- return Promise . resolve ( false ) ;
525- }
526-
527498 if ( ! this . _connections [ connectionId ] ) {
528499 // No active connection(s) to remove.
529500 vscode . window . showErrorMessage ( 'Connection does not exist.' ) ;
@@ -545,6 +516,11 @@ export default class ConnectionController {
545516 await this . disconnect ( ) ;
546517 }
547518
519+ if ( ! this . _connections [ connectionId ] ) {
520+ // If the connection was removed while we were disconnecting we resolve.
521+ return Promise . resolve ( false ) ;
522+ }
523+
548524 await this . removeSavedConnection ( connectionId ) ;
549525
550526 vscode . window . showInformationMessage ( 'MongoDB connection removed.' ) ;
@@ -555,24 +531,6 @@ export default class ConnectionController {
555531 public async onRemoveMongoDBConnection ( ) : Promise < boolean > {
556532 log . info ( 'mdb.removeConnection command called' ) ;
557533
558- // Ensure we aren't currently connecting.
559- if ( this . _connecting ) {
560- vscode . window . showErrorMessage (
561- 'Unable to remove connection: currently connecting.'
562- ) ;
563-
564- return Promise . resolve ( false ) ;
565- }
566-
567- // Ensure we aren't currently disconnecting.
568- if ( this . _disconnecting ) {
569- vscode . window . showErrorMessage (
570- 'Unable to remove connection: currently disconnecting.'
571- ) ;
572-
573- return Promise . resolve ( false ) ;
574- }
575-
576534 const connectionIds = Object . keys ( this . _connections ) ;
577535
578536 if ( connectionIds . length === 0 ) {
@@ -591,13 +549,13 @@ export default class ConnectionController {
591549 const connectionNameToRemove :
592550 | string
593551 | undefined = await vscode . window . showQuickPick (
594- connectionIds . map (
595- ( id , index ) => `${ index + 1 } : ${ this . _connections [ id ] . name } `
596- ) ,
597- {
598- placeHolder : 'Choose a connection to remove...'
599- }
600- ) ;
552+ connectionIds . map (
553+ ( id , index ) => `${ index + 1 } : ${ this . _connections [ id ] . name } `
554+ ) ,
555+ {
556+ placeHolder : 'Choose a connection to remove...'
557+ }
558+ ) ;
601559
602560 if ( ! connectionNameToRemove ) {
603561 return Promise . resolve ( false ) ;
@@ -729,13 +687,6 @@ export default class ConnectionController {
729687
730688 return ! ! this . _connections [ connectionId ] ;
731689 }
732- public getConnectingConnectionName ( ) : string | null {
733- if ( this . _connectingConnectionId === null ) {
734- return null ;
735- }
736-
737- return this . _connections [ this . _connectingConnectionId ] . name ;
738- }
739690 public getConnectingConnectionId ( ) : string | null {
740691 return this . _connectingConnectionId ;
741692 }
@@ -765,6 +716,11 @@ export default class ConnectionController {
765716 this . _connecting = false ;
766717 this . _disconnecting = false ;
767718 this . _connectingConnectionId = '' ;
719+ this . _connectingVersion = 0 ;
720+ }
721+
722+ public getConnectingVersion ( ) : number {
723+ return this . _connectingVersion ;
768724 }
769725
770726 public setActiveConnection ( newActiveConnection : any ) : void {
0 commit comments