@@ -55,7 +55,7 @@ const RequestState = Object.freeze({
55
55
56
56
class Request {
57
57
constructor ( ttl ) {
58
- this . state = 'pending'
58
+ this . state = RequestState . PENDING
59
59
this . promise = new Promise ( ( resolve , reject ) => {
60
60
this . _resolve = value => {
61
61
clearTimeout ( this . _timeout )
@@ -69,12 +69,12 @@ class Request {
69
69
}
70
70
if ( typeof ttl === 'number' && ttl >= 0 ) {
71
71
const err = new Error ( `Pool resource could not be acquired within ${ ttl / 1000 } s` )
72
- this . _timeout = setTimeout ( ( ) => this . _reject ( err ) , ttl )
72
+ this . _timeout = setTimeout ( ( ) => this . _reject ( err ) , ttl ) . unref ( )
73
73
}
74
74
} )
75
75
}
76
- resolve ( v ) { if ( this . state === 'pending' ) this . _resolve ( v ) }
77
- reject ( e ) { if ( this . state === 'pending' ) this . _reject ( e ) }
76
+ resolve ( v ) { if ( this . state === RequestState . PENDING ) this . _resolve ( v ) }
77
+ reject ( e ) { if ( this . state === RequestState . PENDING ) this . _reject ( e ) }
78
78
}
79
79
80
80
class PooledResource {
@@ -131,7 +131,9 @@ constructor (factory, options = {}) {
131
131
this . _queue = [ ]
132
132
133
133
this . #scheduleEviction( )
134
- for ( let i = 0 ; i < this . options . min - this . size ; i ++ ) this . #createResource( )
134
+
135
+ const initial = this . options . min - this . size
136
+ for ( let i = 0 ; i < initial ; i ++ ) this . #createResource( )
135
137
}
136
138
137
139
async acquire ( ) {
@@ -171,7 +173,7 @@ constructor (factory, options = {}) {
171
173
172
174
async clear ( ) {
173
175
await Promise . allSettled ( Array . from ( this . _creates ) )
174
- await Promise . allSettled ( Array . from ( this . _available ) . map ( resource => this . #destroy( resource ) ) )
176
+ await Promise . allSettled ( Array . from ( this . _all ) . map ( resource => this . #destroy( resource ) ) )
175
177
}
176
178
177
179
async #createResource( ) {
@@ -248,16 +250,23 @@ constructor (factory, options = {}) {
248
250
this . _available . delete ( resource )
249
251
this . _loans . delete ( resource . obj )
250
252
try {
251
- await this . factory . destroy ( resource . obj )
253
+ const destroyPromise = Promise . resolve ( this . factory . destroy ( resource . obj ) )
254
+ const { destroyTimeoutMillis } = this . options
255
+ if ( destroyTimeoutMillis && destroyTimeoutMillis > 0 ) {
256
+ const timeout = new Promise ( ( _ , reject ) =>
257
+ setTimeout ( ( ) => reject ( new Error ( `Resource destruction timed out after ${ destroyTimeoutMillis } ms` ) ) , destroyTimeoutMillis ) . unref ( )
258
+ )
259
+ await Promise . race ( [ destroyPromise , timeout ] )
260
+ } else {
261
+ await destroyPromise
262
+ }
252
263
} catch ( e ) {
253
264
LOG . error ( e )
254
265
/* FIXME: We have to ignore errors here due to a TypeError in hdb */
255
266
/* This was also a problem with the old (generic-pool) implementation */
256
267
/* Root cause in hdb needs to be fixed */
257
268
} finally {
258
- if ( ! this . _draining && this . size < this . options . min ) {
259
- await this . #createResource( )
260
- }
269
+ if ( ! this . _draining && this . size < this . options . min ) this . #createResource( )
261
270
}
262
271
}
263
272
@@ -266,14 +275,19 @@ constructor (factory, options = {}) {
266
275
if ( evictionRunIntervalMillis <= 0 ) return
267
276
this . _scheduledEviction = setTimeout ( async ( ) => {
268
277
try {
269
- const resourcesToEvict = Array . from ( this . _available )
270
- . slice ( 0 , numTestsPerEvictionRun )
271
- . filter ( resource => {
272
- const idleTime = Date . now ( ) - resource . lastIdleTime
273
- const softEvict = softIdleTimeoutMillis > 0 && softIdleTimeoutMillis < idleTime && min < this . _available . size
274
- return softEvict || idleTimeoutMillis < idleTime
275
- } )
276
- await Promise . all ( resourcesToEvict . map ( resource => this . #destroy( resource ) ) )
278
+ const evictionCandidates = Array . from ( this . _available ) . slice ( 0 , numTestsPerEvictionRun )
279
+ const destructionPromises = [ ]
280
+ for ( const resource of evictionCandidates ) {
281
+ const idleTime = Date . now ( ) - resource . lastIdleTime
282
+ const softEvict = softIdleTimeoutMillis > 0 && softIdleTimeoutMillis < idleTime && this . _all . size > min
283
+ const hardEvict = idleTimeoutMillis < idleTime
284
+ if ( softEvict || hardEvict ) {
285
+ if ( this . _available . delete ( resource ) ) {
286
+ destructionPromises . push ( this . #destroy( resource ) )
287
+ }
288
+ }
289
+ }
290
+ await Promise . all ( destructionPromises )
277
291
} finally {
278
292
this . #scheduleEviction( )
279
293
}
0 commit comments