|
3 | 3 | const EventEmitter = require("events").EventEmitter; |
4 | 4 |
|
5 | 5 | const factoryValidator = require("./factoryValidator"); |
| 6 | +const errors = require('./errors') |
6 | 7 | const PoolOptions = require("./PoolOptions"); |
7 | 8 | const ResourceRequest = require("./ResourceRequest"); |
8 | 9 | const ResourceLoan = require("./ResourceLoan"); |
@@ -123,6 +124,12 @@ class Pool extends EventEmitter { |
123 | 124 | */ |
124 | 125 | this._scheduledEviction = null; |
125 | 126 |
|
| 127 | + /** |
| 128 | + * counter of consequent failures to create resource |
| 129 | + * @type {Number} |
| 130 | + */ |
| 131 | + this._failedTries = 0 |
| 132 | + |
126 | 133 | // create initial resources (if factory.min > 0) |
127 | 134 | if (this._config.autostart === true) { |
128 | 135 | this.start(); |
@@ -215,6 +222,15 @@ class Pool extends EventEmitter { |
215 | 222 | return; |
216 | 223 | } |
217 | 224 |
|
| 225 | + // Try counter exceeded - reject resource request to next waiting client |
| 226 | + if ( |
| 227 | + this._config.maxTries > 0 && |
| 228 | + this._failedTries >= this._config.maxTries |
| 229 | + ) { |
| 230 | + this._dispatchPooledResourceToNextWaitingClient() |
| 231 | + return |
| 232 | + } |
| 233 | + |
218 | 234 | const resourceShortfall = |
219 | 235 | numWaitingClients - this._potentiallyAllocableResourceCount; |
220 | 236 |
|
@@ -267,15 +283,27 @@ class Pool extends EventEmitter { |
267 | 283 | ) { |
268 | 284 | // While we were away either all the waiting clients timed out |
269 | 285 | // or were somehow fulfilled. put our pooledResource back. |
270 | | - this._addPooledResourceToAvailableObjects(pooledResource); |
| 286 | + if (pooledResource) { |
| 287 | + // While we were away either all the waiting clients timed out |
| 288 | + // or were somehow fulfilled. put our pooledResource back. |
| 289 | + this._addPooledResourceToAvailableObjects(pooledResource) |
| 290 | + } |
271 | 291 | // TODO: do need to trigger anything before we leave? |
272 | 292 | return false; |
273 | 293 | } |
274 | | - const loan = new ResourceLoan(pooledResource, this._Promise); |
275 | | - this._resourceLoans.set(pooledResource.obj, loan); |
276 | | - pooledResource.allocate(); |
277 | | - clientResourceRequest.resolve(pooledResource.obj); |
278 | | - return true; |
| 294 | + if (pooledResource) { |
| 295 | + const loan = new ResourceLoan(pooledResource, this._Promise) |
| 296 | + this._resourceLoans.set(pooledResource.obj, loan) |
| 297 | + pooledResource.allocate() |
| 298 | + clientResourceRequest.resolve(pooledResource.obj) |
| 299 | + } else { |
| 300 | + let errorMessage = 'Failed to create resource' |
| 301 | + if (this._config.maxTries > 0 && this._failedTries >= this._config.maxTries) { |
| 302 | + errorMessage = 'Failed to create resource ' + this._failedTries + ' times in a row' |
| 303 | + } |
| 304 | + clientResourceRequest.reject(new errors.ResourceCreationError(errorMessage)) |
| 305 | + } |
| 306 | + return true |
279 | 307 | } |
280 | 308 |
|
281 | 309 | /** |
@@ -304,12 +332,21 @@ class Pool extends EventEmitter { |
304 | 332 | * @private |
305 | 333 | */ |
306 | 334 | _createResource() { |
| 335 | + // Do not attempt to create resource if reached maximum number of consequent failures |
| 336 | + if ( |
| 337 | + this._config.maxTries > 0 && |
| 338 | + this._failedTries >= this._config.maxTries |
| 339 | + ) { |
| 340 | + return |
| 341 | + } |
307 | 342 | // An attempt to create a resource |
308 | 343 | const factoryPromise = this._factory.create(); |
309 | 344 | const wrappedFactoryPromise = this._Promise.resolve(factoryPromise); |
310 | 345 |
|
311 | 346 | this._trackOperation(wrappedFactoryPromise, this._factoryCreateOperations) |
312 | 347 | .then(resource => { |
| 348 | + // Resource created successfully - reset fail counter |
| 349 | + this._failedTries = 0 |
313 | 350 | this._handleNewResource(resource); |
314 | 351 | return null; |
315 | 352 | }) |
@@ -435,6 +472,10 @@ class Pool extends EventEmitter { |
435 | 472 | ); |
436 | 473 | } |
437 | 474 |
|
| 475 | + // Reset fail counter - maybe resource will be created this time |
| 476 | + // (for example network is restored and connection can be made) |
| 477 | + this._failedTries = 0 |
| 478 | + |
438 | 479 | // TODO: should we defer this check till after this event loop incase "the situation" changes in the meantime |
439 | 480 | if ( |
440 | 481 | this._config.maxWaitingClients !== undefined && |
|
0 commit comments