@@ -69,6 +69,7 @@ export class CloudSQLInstance {
6969 private scheduledRefreshID ?: ReturnType < typeof setTimeout > | null = undefined ;
7070 /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
7171 private throttle ?: any ;
72+ private closed = false ;
7273 public readonly instanceInfo : InstanceConnectionInfo ;
7374 public ephemeralCert ?: SslCert ;
7475 public host ?: string ;
@@ -106,37 +107,45 @@ export class CloudSQLInstance {
106107 } ) as ReturnType < typeof pThrottle > ;
107108 }
108109
109- forceRefresh ( ) {
110+ forceRefresh ( ) : Promise < void > {
110111 // if a refresh is already ongoing, just await for its promise to fulfill
111112 // so that a new instance info is available before reconnecting
112113 if ( this . next ) {
113- return ;
114+ return new Promise ( resolve => {
115+ if ( this . next ) {
116+ this . next . finally ( resolve ) ;
117+ } else {
118+ resolve ( ) ;
119+ }
120+ } ) ;
114121 }
122+
115123 this . cancelRefresh ( ) ;
116124 this . scheduleRefresh ( 0 ) ;
117- }
118125
119- // refreshComplete Returns a promise that resolves when the current refresh
120- // cycle has completed, either with success or failure. If no refresh is
121- // in progress, the promise will resolve immediately.
122- refreshComplete ( ) : Promise < void > {
123- return new Promise ( ( resolve ) => {
126+ return new Promise ( resolve => {
124127 // setTimeout() to yield execution to allow other refresh background
125- // tasks to start.
126- setTimeout ( ( ) => {
127- if ( this . next ) {
128+ // task to start.
129+ setTimeout ( ( ) => {
130+ if ( this . next ) {
128131 // If there is a refresh promise in progress, resolve this promise
129132 // when the refresh is complete.
130- this . next . finally ( resolve )
133+ this . next . finally ( resolve ) ;
131134 } else {
132135 // Else resolve immediately.
133- resolve ( )
136+ resolve ( ) ;
134137 }
135138 } , 0 ) ;
136139 } ) ;
137140 }
138141
139142 refresh ( ) : Promise < RefreshResult > {
143+ if ( this . closed ) {
144+ this . scheduledRefreshID = undefined ;
145+ this . next = undefined ;
146+ return Promise . reject ( 'closed' ) ;
147+ }
148+
140149 const currentRefreshId = this . scheduledRefreshID ;
141150
142151 // Since forceRefresh might be invoked during an ongoing refresh
@@ -203,6 +212,12 @@ export class CloudSQLInstance {
203212 // used to create new connections to a Cloud SQL instance. It throws in
204213 // case any of the internal steps fails.
205214 private async performRefresh ( ) : Promise < RefreshResult > {
215+ if ( this . closed ) {
216+ // The connector may be closed while the rate limiter delayed
217+ // a call to performRefresh() so check this.closed before continuing.
218+ return Promise . reject ( 'closed' ) ;
219+ }
220+
206221 const rsaKeys : RSAKeys = await generateKeys ( ) ;
207222 const metadata : InstanceMetadata =
208223 await this . sqlAdminFetcher . getInstanceMetadata ( this . instanceInfo ) ;
@@ -264,6 +279,9 @@ export class CloudSQLInstance {
264279 }
265280
266281 private scheduleRefresh ( delay : number ) : void {
282+ if ( this . closed ) {
283+ return ;
284+ }
267285 this . scheduledRefreshID = setTimeout ( ( ) => this . refresh ( ) , delay ) ;
268286 }
269287
@@ -280,4 +298,11 @@ export class CloudSQLInstance {
280298 setEstablishedConnection ( ) : void {
281299 this . establishedConnection = true ;
282300 }
301+
302+ // close stops any refresh process in progress and prevents future refresh
303+ // connections.
304+ close ( ) : void {
305+ this . closed = true ;
306+ this . cancelRefresh ( ) ;
307+ }
283308}
0 commit comments