diff --git a/src/internal/pool.js b/src/internal/pool.js index 7f6d632a3..2563226b1 100644 --- a/src/internal/pool.js +++ b/src/internal/pool.js @@ -73,11 +73,18 @@ class Pool { const key = address.asKey() if (resource) { - resourceAcquired(key, this._activeResourceCounts) - if (this._log.isDebugEnabled()) { - this._log.debug(`${resource} acquired from the pool ${key}`) + if ( + this._maxSize && + this.activeResourceCount(address) >= this._maxSize + ) { + this._destroy(resource) + } else { + resourceAcquired(key, this._activeResourceCounts) + if (this._log.isDebugEnabled()) { + this._log.debug(`${resource} acquired from the pool ${key}`) + } + return resource } - return resource } // We're out of resources and will try to acquire later on when an existing resource is released. @@ -104,11 +111,11 @@ class Pool { // request already resolved/rejected by the release operation; nothing to do } else { // request is still pending and needs to be failed + const activeCount = this.activeResourceCount(address) + const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - `Connection acquisition timed out in ${ - this._acquisitionTimeout - } ms.` + `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Poos status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } @@ -218,7 +225,10 @@ class Pool { } else { if (this._installIdleObserver) { this._installIdleObserver(resource, { - onError: () => { + onError: error => { + this._log.debug( + `Idle connection ${resource} destroyed because of error: ${error}` + ) const pool = this._pools[key] if (pool) { this._pools[key] = pool.filter(r => r !== resource) diff --git a/test/driver.test.js b/test/driver.test.js index 31822a6da..de693e8be 100644 --- a/test/driver.test.js +++ b/test/driver.test.js @@ -44,6 +44,40 @@ describe('#integration driver', () => { } }) + it('should not decrease active connection count after driver close', done => { + // Given + const config = { + maxConnectionPoolSize: 2, + connectionAcquisitionTimeout: 0, + encrypted: false + } + driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken, config) + + function beginTxWithoutCommit (driver) { + const session = driver.session() + const tx = session.beginTransaction() + return tx.run('RETURN 1') + } + // When + + const result1 = beginTxWithoutCommit(driver) + const result2 = beginTxWithoutCommit(driver) + + Promise.all([result1, result2]).then(results => { + driver.close() + beginTxWithoutCommit(driver).catch(() => { + var pool = driver._connectionProvider._connectionPool + var serverKey = Object.keys(pool._activeResourceCounts)[0] + expect(pool._activeResourceCounts[serverKey]).toEqual(2) + expect(serverKey in pool._pools).toBeFalsy() + expect( + Object.keys(driver._connectionProvider._openConnections).length + ).toEqual(2) + done() + }) + }) + }, 10000) + it('should expose sessions', () => { // Given driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken)