Skip to content

Commit 671f070

Browse files
authored
Refactory Pool module (#930)
The state of the pool and the resource list weren't bounded together as it supposed to. This scenario makes the code prune to bugs and inconsistency in the long run. Merge the resource list (a.k.a. Pool) and PoolState in the same object makes the code easier to understand and more cohesive.
1 parent 0e0b975 commit 671f070

File tree

1 file changed

+49
-33
lines changed
  • packages/bolt-connection/src/pool

1 file changed

+49
-33
lines changed

packages/bolt-connection/src/pool/pool.js

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class Pool {
6262
this._pendingCreates = {}
6363
this._acquireRequests = {}
6464
this._activeResourceCounts = {}
65-
this._poolState = {}
6665
this._release = this._release.bind(this)
6766
this._log = log
6867
this._closed = false
@@ -111,7 +110,6 @@ class Pool {
111110

112111
request = new PendingRequest(key, resolve, reject, timeoutId, this._log)
113112
allRequests[key].push(request)
114-
115113
this._processPendingAcquireRequests(address)
116114
})
117115
}
@@ -177,21 +175,23 @@ class Pool {
177175
return this._activeResourceCounts[address.asKey()] || 0
178176
}
179177

178+
_getOrInitializePoolFor (key) {
179+
let pool = this._pools[key]
180+
if (!pool) {
181+
pool = new SingleAddressPool()
182+
this._pools[key] = pool
183+
this._pendingCreates[key] = 0
184+
}
185+
return pool
186+
}
187+
180188
async _acquire (address) {
181189
if (this._closed) {
182190
throw newError('Pool is closed, it is no more able to serve requests.')
183191
}
184192

185193
const key = address.asKey()
186-
let pool = this._pools[key]
187-
let poolState = this._poolState[key]
188-
if (!pool) {
189-
pool = []
190-
poolState = new PoolState()
191-
this._pools[key] = pool
192-
this._pendingCreates[key] = 0
193-
this._poolState[key] = poolState
194-
}
194+
const pool = this._getOrInitializePoolFor(key)
195195
while (pool.length) {
196196
const resource = pool.pop()
197197

@@ -205,7 +205,7 @@ class Pool {
205205
if (this._log.isDebugEnabled()) {
206206
this._log.debug(`${resource} acquired from the pool ${key}`)
207207
}
208-
return resource
208+
return { resource, pool }
209209
} else {
210210
await this._destroy(resource)
211211
}
@@ -219,7 +219,7 @@ class Pool {
219219
this.activeResourceCount(address) + this._pendingCreates[key]
220220
if (numConnections >= this._maxSize) {
221221
// Will put this request in queue instead since the pool is full
222-
return null
222+
return { resource: null, pool }
223223
}
224224
}
225225

@@ -229,7 +229,7 @@ class Pool {
229229
let resource
230230
try {
231231
// Invoke callback that creates actual connection
232-
resource = await this._create(address, (address, resource) => this._release(poolState, address, resource))
232+
resource = await this._create(address, (address, resource) => this._release(address, resource, pool))
233233

234234
resourceAcquired(key, this._activeResourceCounts)
235235
if (this._log.isDebugEnabled()) {
@@ -238,14 +238,13 @@ class Pool {
238238
} finally {
239239
this._pendingCreates[key] = this._pendingCreates[key] - 1
240240
}
241-
return resource
241+
return { resource, pool }
242242
}
243243

244-
async _release (poolState, address, resource) {
244+
async _release (address, resource, pool) {
245245
const key = address.asKey()
246-
const pool = this._pools[key]
247246

248-
if (pool && poolState.isActive()) {
247+
if (pool.isActive()) {
249248
// there exist idle connections for the given key
250249
if (!this._validate(resource)) {
251250
if (this._log.isDebugEnabled()) {
@@ -292,24 +291,23 @@ class Pool {
292291
}
293292

294293
async _purgeKey (key) {
295-
const pool = this._pools[key] || []
296-
const poolState = this._poolState[key] || new PoolState()
297-
while (pool.length) {
298-
const resource = pool.pop()
299-
if (this._removeIdleObserver) {
300-
this._removeIdleObserver(resource)
294+
const pool = this._pools[key]
295+
if (pool) {
296+
while (pool.length) {
297+
const resource = pool.pop()
298+
if (this._removeIdleObserver) {
299+
this._removeIdleObserver(resource)
300+
}
301+
await this._destroy(resource)
301302
}
302-
await this._destroy(resource)
303+
pool.close()
304+
delete this._pools[key]
303305
}
304-
poolState.close()
305-
delete this._pools[key]
306-
delete this._poolState[key]
307306
}
308307

309308
_processPendingAcquireRequests (address) {
310309
const key = address.asKey()
311310
const requests = this._acquireRequests[key]
312-
const poolState = this._poolState[key] || new PoolState()
313311
if (requests) {
314312
const pendingRequest = requests.shift() // pop a pending acquire request
315313

@@ -319,16 +317,16 @@ class Pool {
319317
// failed to acquire/create a new connection to resolve the pending acquire request
320318
// propagate the error by failing the pending request
321319
pendingRequest.reject(error)
322-
return null
320+
return { resource: null }
323321
})
324-
.then(resource => {
322+
.then(({ resource, pool }) => {
325323
if (resource) {
326324
// managed to acquire a valid resource from the pool
327325

328326
if (pendingRequest.isCompleted()) {
329327
// request has been completed, most likely failed by a timeout
330328
// return the acquired resource back to the pool
331-
this._release(poolState, address, resource)
329+
this._release(address, resource, pool)
332330
} else {
333331
// request is still pending and can be resolved with the newly acquired resource
334332
pendingRequest.resolve(resource) // resolve the pending request with the acquired resource
@@ -415,9 +413,10 @@ class PendingRequest {
415413
}
416414
}
417415

418-
class PoolState {
416+
class SingleAddressPool {
419417
constructor () {
420418
this._active = true
419+
this._elements = []
421420
}
422421

423422
isActive () {
@@ -427,6 +426,23 @@ class PoolState {
427426
close () {
428427
this._active = false
429428
}
429+
430+
filter (predicate) {
431+
this._elements = this._elements.filter(predicate)
432+
return this
433+
}
434+
435+
get length () {
436+
return this._elements.length
437+
}
438+
439+
pop () {
440+
return this._elements.pop()
441+
}
442+
443+
push (element) {
444+
return this._elements.push(element)
445+
}
430446
}
431447

432448
export default Pool

0 commit comments

Comments
 (0)