From 70a50528b9c0ab84ad000efd5ca9f782b014b83e Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 09:44:51 +0200 Subject: [PATCH 01/14] unify connection acquisition timeout with other drivers --- .../connection-provider/connection-provider-routing.js | 5 +++-- packages/core/src/internal/pool/pool.ts | 4 +++- .../connection-provider/connection-provider-routing.js | 5 +++-- .../neo4j-driver-deno/lib/core/internal/pool/pool.ts | 4 +++- packages/testkit-backend/src/skipped-tests/common.js | 10 ---------- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js index 38243b868..868710261 100644 --- a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js +++ b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js @@ -152,6 +152,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider (error, address, conn) => this._handleSecurityError(error, address, conn, context.database) ) + this._startTime = new Date().getTime() let conn if (this.SSREnabled() && homeDb !== undefined && database === '') { const currentRoutingTable = this._routingTableRegistry.get( @@ -205,7 +206,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } try { - const connection = await this._connectionPool.acquire({ auth }, address) + const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, address) if (auth) { await this._verifyStickyConnection({ @@ -585,7 +586,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmarks, impersonatedUser, auth) { try { - const connection = await this._connectionPool.acquire({ auth }, routerAddress) + const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, routerAddress) if (auth) { await this._verifyStickyConnection({ diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 06920c176..c34fa0960 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -139,11 +139,13 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( + // @ts-expect-error `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - }, this._acquisitionTimeout) + // @ts-expect-error + }, this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)) if (typeof timeoutId === 'object') { // eslint-disable-next-line diff --git a/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js b/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js index 46014726f..c60d00035 100644 --- a/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js +++ b/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js @@ -152,6 +152,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider (error, address, conn) => this._handleSecurityError(error, address, conn, context.database) ) + this._startTime = new Date().getTime() let conn if (this.SSREnabled() && homeDb !== undefined && database === '') { const currentRoutingTable = this._routingTableRegistry.get( @@ -205,7 +206,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } try { - const connection = await this._connectionPool.acquire({ auth }, address) + const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, address) if (auth) { await this._verifyStickyConnection({ @@ -585,7 +586,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmarks, impersonatedUser, auth) { try { - const connection = await this._connectionPool.acquire({ auth }, routerAddress) + const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, routerAddress) if (auth) { await this._verifyStickyConnection({ diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index ecf4f1085..155017475 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -139,11 +139,13 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( + // @ts-ignore `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - }, this._acquisitionTimeout) + // @ts-ignore + }, this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)) if (typeof timeoutId === 'object') { // eslint-disable-next-line diff --git a/packages/testkit-backend/src/skipped-tests/common.js b/packages/testkit-backend/src/skipped-tests/common.js index 1b23dfe04..e39188f31 100644 --- a/packages/testkit-backend/src/skipped-tests/common.js +++ b/packages/testkit-backend/src/skipped-tests/common.js @@ -169,12 +169,6 @@ const skippedTests = [ 'Flaky tests, requires investigation', ifEndsWith('.test_should_fail_when_writing_to_unexpectedly_interrupting_writers_using_tx_function') ), - skip( - 'TODO: ConnectionAcquisitionTimeout cancels handshake with the router', - ifEquals( - 'stub.driver_parameters.test_connection_acquisition_timeout_ms.TestConnectionAcquisitionTimeoutMs.test_does_not_encompass_router_handshake' - ) - ), skip( 'Backend does not support async AuthTokenManager.handleSecurityException', ifStartsWith('stub.authorization.test_auth_token_manager.TestAuthTokenManager') @@ -198,10 +192,6 @@ const skippedTests = [ skip( 'Needs trying all DNS resolved addresses for hosts in the routing table', ifEndsWith('.test_ipv6_read').and(startsWith('stub.routing.test_routing_')) - ), - skip( - 'Driver has separate timeouts for every connection it attempts to open. This will change in 6.0', - ifEquals('stub.homedb.test_homedb.TestHomeDbMixedCluster.test_connection_acquisition_timeout_during_fallback') ) ] From 9d10bbc16af797dc6552ea5fbea0e83cc738e855 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 09:56:54 +0200 Subject: [PATCH 02/14] deno sync --- packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index 155017475..ff7401e36 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -139,12 +139,12 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - // @ts-ignore + // @ts-expect-error `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - // @ts-ignore + // @ts-expect-error }, this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)) if (typeof timeoutId === 'object') { From 1c805cdca4febf754e45bd17d87bba38160f0784 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:01:44 +0200 Subject: [PATCH 03/14] remove unused expect error --- packages/core/src/internal/pool/pool.ts | 1 - packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index c34fa0960..5c988bf0c 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -139,7 +139,6 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - // @ts-expect-error `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index ff7401e36..4b5c80d01 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -139,7 +139,6 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - // @ts-expect-error `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) From d0623c7fe02b707d2c85393afb95b6661d167d5d Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:22:31 +0200 Subject: [PATCH 04/14] testing fixes --- .../connection-provider-routing.test.js | 8 ++++---- packages/testkit-backend/src/skipped-tests/common.js | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js b/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js index 297e87d78..56602ddf6 100644 --- a/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js +++ b/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js @@ -3494,7 +3494,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalledWith({ auth }, server3) + expect(poolAcquire).toHaveBeenCalled() expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3536,7 +3536,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalledWith({ auth }, server1) + expect(poolAcquire).toHaveBeenCalled() expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3580,7 +3580,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalledWith({ auth }, server0) + expect(poolAcquire).toHaveBeenCalled() expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3609,7 +3609,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalledWith({ auth }, server0) + expect(poolAcquire).toHaveBeenCalled() expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) diff --git a/packages/testkit-backend/src/skipped-tests/common.js b/packages/testkit-backend/src/skipped-tests/common.js index e39188f31..6c62a27e7 100644 --- a/packages/testkit-backend/src/skipped-tests/common.js +++ b/packages/testkit-backend/src/skipped-tests/common.js @@ -169,6 +169,12 @@ const skippedTests = [ 'Flaky tests, requires investigation', ifEndsWith('.test_should_fail_when_writing_to_unexpectedly_interrupting_writers_using_tx_function') ), + skip( + 'TODO: ConnectionAcquisitionTimeout cancels handshake with the router', + ifEquals( + 'stub.driver_parameters.test_connection_acquisition_timeout_ms.TestConnectionAcquisitionTimeoutMs.test_does_not_encompass_router_handshake' + ) + ), skip( 'Backend does not support async AuthTokenManager.handleSecurityException', ifStartsWith('stub.authorization.test_auth_token_manager.TestAuthTokenManager') From 8f9125b520f5b16777b195da54f4f526ea1c0691 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:56:42 +0200 Subject: [PATCH 05/14] test extend default timeout --- packages/core/src/types.ts | 4 ++-- packages/neo4j-driver-deno/lib/core/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 8f60394a3..b9de01bfa 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -168,11 +168,11 @@ export class Config { * The maximum amount of time to wait to acquire a connection from the pool (to either create a new * connection or borrow an existing one). * - * **Default**: ```60000``` (1 minute) + * **Default**: ```120000``` (2 minutes) * * @type {number|undefined} */ - this.connectionAcquisitionTimeout = 60000 // 1 minute + this.connectionAcquisitionTimeout = 120000 // 2 minutes /** * Specify the maximum time in milliseconds transactions are allowed to retry via diff --git a/packages/neo4j-driver-deno/lib/core/types.ts b/packages/neo4j-driver-deno/lib/core/types.ts index 7cdc1e747..892d5f90e 100644 --- a/packages/neo4j-driver-deno/lib/core/types.ts +++ b/packages/neo4j-driver-deno/lib/core/types.ts @@ -168,11 +168,11 @@ export class Config { * The maximum amount of time to wait to acquire a connection from the pool (to either create a new * connection or borrow an existing one). * - * **Default**: ```60000``` (1 minute) + * **Default**: ```120000``` (2 minutes) * * @type {number|undefined} */ - this.connectionAcquisitionTimeout = 60000 // 1 minute + this.connectionAcquisitionTimeout = 120000 // 2 minutes /** * Specify the maximum time in milliseconds transactions are allowed to retry via From 3a658c2a6f9f36adfd8837e645acfee9c0f458ef Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 12:05:36 +0200 Subject: [PATCH 06/14] fix start time math --- .../connection-provider/connection-provider-routing.js | 9 +++++++-- packages/core/src/internal/pool/pool.ts | 3 ++- packages/core/src/types.ts | 4 ++-- .../connection-provider/connection-provider-routing.js | 9 +++++++-- .../neo4j-driver-deno/lib/core/internal/pool/pool.ts | 3 ++- packages/neo4j-driver-deno/lib/core/types.ts | 4 ++-- 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js index 868710261..20423fb1b 100644 --- a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js +++ b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js @@ -89,6 +89,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider this._loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy( this._connectionPool ) + this._startTime = 0 this._hostNameResolver = hostNameResolver this._dnsResolver = new HostNameResolver() this._log = log @@ -162,6 +163,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider if (currentRoutingTable && !currentRoutingTable.isStaleFor(accessMode)) { conn = await this.getConnectionFromRoutingTable(currentRoutingTable, auth, accessMode, databaseSpecificErrorHandler) if (this.SSREnabled()) { + this._startTime = 0 return conn } conn.release() @@ -180,6 +182,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } } }) + this._startTime = 0 return this.getConnectionFromRoutingTable(routingTable, auth, accessMode, databaseSpecificErrorHandler) } @@ -206,7 +209,8 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } try { - const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, address) + const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 + const connection = await this._connectionPool.acquire({ auth, elapsedTime }, address) if (auth) { await this._verifyStickyConnection({ @@ -586,7 +590,8 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmarks, impersonatedUser, auth) { try { - const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, routerAddress) + const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 + const connection = await this._connectionPool.acquire({ auth, elapsedTime }, routerAddress) if (auth) { await this._verifyStickyConnection({ diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 5c988bf0c..1109e1334 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -139,7 +139,8 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` + // @ts-expect-error + `Connection acquisition timed out in ${this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index b9de01bfa..8f60394a3 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -168,11 +168,11 @@ export class Config { * The maximum amount of time to wait to acquire a connection from the pool (to either create a new * connection or borrow an existing one). * - * **Default**: ```120000``` (2 minutes) + * **Default**: ```60000``` (1 minute) * * @type {number|undefined} */ - this.connectionAcquisitionTimeout = 120000 // 2 minutes + this.connectionAcquisitionTimeout = 60000 // 1 minute /** * Specify the maximum time in milliseconds transactions are allowed to retry via diff --git a/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js b/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js index c60d00035..761c565d6 100644 --- a/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js +++ b/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js @@ -89,6 +89,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider this._loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy( this._connectionPool ) + this._startTime = 0 this._hostNameResolver = hostNameResolver this._dnsResolver = new HostNameResolver() this._log = log @@ -162,6 +163,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider if (currentRoutingTable && !currentRoutingTable.isStaleFor(accessMode)) { conn = await this.getConnectionFromRoutingTable(currentRoutingTable, auth, accessMode, databaseSpecificErrorHandler) if (this.SSREnabled()) { + this._startTime = 0 return conn } conn.release() @@ -180,6 +182,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } } }) + this._startTime = 0 return this.getConnectionFromRoutingTable(routingTable, auth, accessMode, databaseSpecificErrorHandler) } @@ -206,7 +209,8 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } try { - const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, address) + const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 + const connection = await this._connectionPool.acquire({ auth, elapsedTime }, address) if (auth) { await this._verifyStickyConnection({ @@ -586,7 +590,8 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmarks, impersonatedUser, auth) { try { - const connection = await this._connectionPool.acquire({ auth, elapsedTime: new Date().getTime() - this._startTime }, routerAddress) + const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 + const connection = await this._connectionPool.acquire({ auth, elapsedTime }, routerAddress) if (auth) { await this._verifyStickyConnection({ diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index 4b5c80d01..904f10833 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -139,7 +139,8 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` + // @ts-expect-error + `Connection acquisition timed out in ${this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } diff --git a/packages/neo4j-driver-deno/lib/core/types.ts b/packages/neo4j-driver-deno/lib/core/types.ts index 892d5f90e..7cdc1e747 100644 --- a/packages/neo4j-driver-deno/lib/core/types.ts +++ b/packages/neo4j-driver-deno/lib/core/types.ts @@ -168,11 +168,11 @@ export class Config { * The maximum amount of time to wait to acquire a connection from the pool (to either create a new * connection or borrow an existing one). * - * **Default**: ```120000``` (2 minutes) + * **Default**: ```60000``` (1 minute) * * @type {number|undefined} */ - this.connectionAcquisitionTimeout = 120000 // 2 minutes + this.connectionAcquisitionTimeout = 60000 // 1 minute /** * Specify the maximum time in milliseconds transactions are allowed to retry via From 61ff39152674f680d77b1586cbdbe92ca18b699a Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:07:20 +0200 Subject: [PATCH 07/14] fix start time logic --- .../connection-provider/connection-provider-routing.js | 8 ++------ packages/core/src/internal/pool/pool.ts | 8 ++++---- .../connection-provider/connection-provider-routing.js | 8 ++------ packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 8 ++++---- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js index 20423fb1b..5b7de7ee5 100644 --- a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js +++ b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js @@ -163,7 +163,6 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider if (currentRoutingTable && !currentRoutingTable.isStaleFor(accessMode)) { conn = await this.getConnectionFromRoutingTable(currentRoutingTable, auth, accessMode, databaseSpecificErrorHandler) if (this.SSREnabled()) { - this._startTime = 0 return conn } conn.release() @@ -182,7 +181,6 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } } }) - this._startTime = 0 return this.getConnectionFromRoutingTable(routingTable, auth, accessMode, databaseSpecificErrorHandler) } @@ -209,8 +207,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } try { - const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 - const connection = await this._connectionPool.acquire({ auth, elapsedTime }, address) + const connection = await this._connectionPool.acquire({ auth, startTime: this._startTime }, address) if (auth) { await this._verifyStickyConnection({ @@ -590,8 +587,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmarks, impersonatedUser, auth) { try { - const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 - const connection = await this._connectionPool.acquire({ auth, elapsedTime }, routerAddress) + const connection = await this._connectionPool.acquire({ auth, startTime: this._startTime }, routerAddress) if (auth) { await this._verifyStickyConnection({ diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 1109e1334..39e48bc8f 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -117,6 +117,8 @@ class Pool { // We're out of resources and will try to acquire later on when an existing resource is released. const allRequests = this._acquireRequests const requests = allRequests[key] + // @ts-expect-error + const elapsedTime = acquisitionContext.startTime !== 0 ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 if (requests == null) { allRequests[key] = [] } @@ -139,13 +141,11 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - // @ts-expect-error - `Connection acquisition timed out in ${this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` + `Connection acquisition timed out in ${this._acquisitionTimeout - (elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - // @ts-expect-error - }, this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)) + }, this._acquisitionTimeout - (elapsedTime ?? 0)) if (typeof timeoutId === 'object') { // eslint-disable-next-line diff --git a/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js b/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js index 761c565d6..29018f608 100644 --- a/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js +++ b/packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js @@ -163,7 +163,6 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider if (currentRoutingTable && !currentRoutingTable.isStaleFor(accessMode)) { conn = await this.getConnectionFromRoutingTable(currentRoutingTable, auth, accessMode, databaseSpecificErrorHandler) if (this.SSREnabled()) { - this._startTime = 0 return conn } conn.release() @@ -182,7 +181,6 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } } }) - this._startTime = 0 return this.getConnectionFromRoutingTable(routingTable, auth, accessMode, databaseSpecificErrorHandler) } @@ -209,8 +207,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider } try { - const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 - const connection = await this._connectionPool.acquire({ auth, elapsedTime }, address) + const connection = await this._connectionPool.acquire({ auth, startTime: this._startTime }, address) if (auth) { await this._verifyStickyConnection({ @@ -590,8 +587,7 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmarks, impersonatedUser, auth) { try { - const elapsedTime = this._startTime !== 0 ? new Date().getTime() - (this._startTime ?? 0) : 0 - const connection = await this._connectionPool.acquire({ auth, elapsedTime }, routerAddress) + const connection = await this._connectionPool.acquire({ auth, startTime: this._startTime }, routerAddress) if (auth) { await this._verifyStickyConnection({ diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index 904f10833..9c8b57caa 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -117,6 +117,8 @@ class Pool { // We're out of resources and will try to acquire later on when an existing resource is released. const allRequests = this._acquireRequests const requests = allRequests[key] + // @ts-expect-error + const elapsedTime = acquisitionContext.startTime !== 0 ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 if (requests == null) { allRequests[key] = [] } @@ -139,13 +141,11 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - // @ts-expect-error - `Connection acquisition timed out in ${this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` + `Connection acquisition timed out in ${this._acquisitionTimeout - (elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - // @ts-expect-error - }, this._acquisitionTimeout - (acquisitionContext.elapsedTime ?? 0)) + }, this._acquisitionTimeout - (elapsedTime ?? 0)) if (typeof timeoutId === 'object') { // eslint-disable-next-line From 272c2b2f9fb9959bc0b043ad29e8f9ece6696a19 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:41:04 +0200 Subject: [PATCH 08/14] handle undefined start --- packages/core/src/internal/pool/pool.ts | 2 +- packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 39e48bc8f..1b34c1340 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -118,7 +118,7 @@ class Pool { const allRequests = this._acquireRequests const requests = allRequests[key] // @ts-expect-error - const elapsedTime = acquisitionContext.startTime !== 0 ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 + const elapsedTime = (acquisitionContext.startTime != null && acquisitionContext.startTime !== 0) ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 if (requests == null) { allRequests[key] = [] } diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index 9c8b57caa..aebd9aa17 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -118,7 +118,7 @@ class Pool { const allRequests = this._acquireRequests const requests = allRequests[key] // @ts-expect-error - const elapsedTime = acquisitionContext.startTime !== 0 ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 + const elapsedTime = (acquisitionContext.startTime != null && acquisitionContext.startTime !== 0) ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 if (requests == null) { allRequests[key] = [] } From 1510526ebd50bfc8df113651ba6c79fe037117dc Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 4 Jun 2025 15:08:35 +0200 Subject: [PATCH 09/14] change testkit branch --- packages/core/src/internal/pool/pool.ts | 4 ++-- packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 4 ++-- testkit/testkit.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 1b34c1340..8b9f59a8e 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -141,11 +141,11 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - `Connection acquisition timed out in ${this._acquisitionTimeout - (elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` + `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - }, this._acquisitionTimeout - (elapsedTime ?? 0)) + }, this._acquisitionTimeout - elapsedTime) if (typeof timeoutId === 'object') { // eslint-disable-next-line diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index aebd9aa17..2d8b580ba 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -141,11 +141,11 @@ class Pool { const idleCount = this.has(address) ? this._pools[key].length : 0 request.reject( newError( - `Connection acquisition timed out in ${this._acquisitionTimeout - (elapsedTime ?? 0)} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` + `Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.` ) ) } - }, this._acquisitionTimeout - (elapsedTime ?? 0)) + }, this._acquisitionTimeout - elapsedTime) if (typeof timeoutId === 'object') { // eslint-disable-next-line diff --git a/testkit/testkit.json b/testkit/testkit.json index 0b9944108..d670dadc0 100644 --- a/testkit/testkit.json +++ b/testkit/testkit.json @@ -1,6 +1,6 @@ { "testkit": { "uri": "https://github.com/neo4j-drivers/testkit.git", - "ref": "6.x" + "ref": "connection-acquisition-6x-change" } } From 7cf71a869c4c059e313439b1f9d4168c84dc77e4 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:41:05 +0200 Subject: [PATCH 10/14] type acquisitionContext --- packages/core/src/internal/pool/pool.ts | 6 +++--- packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 8b9f59a8e..8142ee1d7 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -28,6 +28,7 @@ type ValidateOnRelease = (resource: R) => (Promise< type InstallObserver = (resource: R, observer: unknown) => void type RemoveObserver = (resource: R) => void interface AcquisitionConfig { requireNew?: boolean } +interface AcquisitionContext { startTime?: number, forceReAuth: boolean, skipReAuth: boolean, auth: object } interface ConstructorParam { create?: Create @@ -111,14 +112,13 @@ class Pool { * @param {boolean} config.requireNew Indicate it requires a new resource * @return {Promise} resource that is ready to use. */ - async acquire (acquisitionContext: unknown, address: ServerAddress, config?: AcquisitionConfig): Promise { + async acquire (acquisitionContext: AcquisitionContext, address: ServerAddress, config?: AcquisitionConfig): Promise { const key = address.asKey() // We're out of resources and will try to acquire later on when an existing resource is released. const allRequests = this._acquireRequests const requests = allRequests[key] - // @ts-expect-error - const elapsedTime = (acquisitionContext.startTime != null && acquisitionContext.startTime !== 0) ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 + const elapsedTime = (acquisitionContext.startTime != null && acquisitionContext.startTime !== 0) ? new Date().getTime() - acquisitionContext.startTime : 0 if (requests == null) { allRequests[key] = [] } diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index 2d8b580ba..dd39cd11a 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -28,6 +28,7 @@ type ValidateOnRelease = (resource: R) => (Promise< type InstallObserver = (resource: R, observer: unknown) => void type RemoveObserver = (resource: R) => void interface AcquisitionConfig { requireNew?: boolean } +interface AcquisitionContext { startTime?: number, forceReAuth: boolean, skipReAuth: boolean, auth: object } interface ConstructorParam { create?: Create @@ -111,14 +112,13 @@ class Pool { * @param {boolean} config.requireNew Indicate it requires a new resource * @return {Promise} resource that is ready to use. */ - async acquire (acquisitionContext: unknown, address: ServerAddress, config?: AcquisitionConfig): Promise { + async acquire (acquisitionContext: AcquisitionContext, address: ServerAddress, config?: AcquisitionConfig): Promise { const key = address.asKey() // We're out of resources and will try to acquire later on when an existing resource is released. const allRequests = this._acquireRequests const requests = allRequests[key] - // @ts-expect-error - const elapsedTime = (acquisitionContext.startTime != null && acquisitionContext.startTime !== 0) ? new Date().getTime() - (acquisitionContext.startTime ?? 0) : 0 + const elapsedTime = (acquisitionContext.startTime != null && acquisitionContext.startTime !== 0) ? new Date().getTime() - acquisitionContext.startTime : 0 if (requests == null) { allRequests[key] = [] } From 62f46970628de02e06ba74dd7ee3cde96ccf79f9 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:05:58 +0200 Subject: [PATCH 11/14] made context properties optional --- packages/core/src/internal/pool/pool.ts | 2 +- packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index 8142ee1d7..ef0a772d3 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -28,7 +28,7 @@ type ValidateOnRelease = (resource: R) => (Promise< type InstallObserver = (resource: R, observer: unknown) => void type RemoveObserver = (resource: R) => void interface AcquisitionConfig { requireNew?: boolean } -interface AcquisitionContext { startTime?: number, forceReAuth: boolean, skipReAuth: boolean, auth: object } +interface AcquisitionContext { startTime?: number, forceReAuth?: boolean, skipReAuth?: boolean, auth?: object } interface ConstructorParam { create?: Create diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index dd39cd11a..7f4c95208 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -28,7 +28,7 @@ type ValidateOnRelease = (resource: R) => (Promise< type InstallObserver = (resource: R, observer: unknown) => void type RemoveObserver = (resource: R) => void interface AcquisitionConfig { requireNew?: boolean } -interface AcquisitionContext { startTime?: number, forceReAuth: boolean, skipReAuth: boolean, auth: object } +interface AcquisitionContext { startTime?: number, forceReAuth?: boolean, skipReAuth?: boolean, auth?: object } interface ConstructorParam { create?: Create From bf780a2b03312efa14c721121e36c4d67a5fd20d Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:56:01 +0200 Subject: [PATCH 12/14] add triggerValidation to context --- packages/core/src/internal/pool/pool.ts | 2 +- packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/internal/pool/pool.ts b/packages/core/src/internal/pool/pool.ts index ef0a772d3..43ec04dde 100644 --- a/packages/core/src/internal/pool/pool.ts +++ b/packages/core/src/internal/pool/pool.ts @@ -28,7 +28,7 @@ type ValidateOnRelease = (resource: R) => (Promise< type InstallObserver = (resource: R, observer: unknown) => void type RemoveObserver = (resource: R) => void interface AcquisitionConfig { requireNew?: boolean } -interface AcquisitionContext { startTime?: number, forceReAuth?: boolean, skipReAuth?: boolean, auth?: object } +interface AcquisitionContext { startTime?: number, forceReAuth?: boolean, skipReAuth?: boolean, auth?: object, triggerValidation?: boolean } interface ConstructorParam { create?: Create diff --git a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts index 7f4c95208..7408c6dcd 100644 --- a/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts +++ b/packages/neo4j-driver-deno/lib/core/internal/pool/pool.ts @@ -28,7 +28,7 @@ type ValidateOnRelease = (resource: R) => (Promise< type InstallObserver = (resource: R, observer: unknown) => void type RemoveObserver = (resource: R) => void interface AcquisitionConfig { requireNew?: boolean } -interface AcquisitionContext { startTime?: number, forceReAuth?: boolean, skipReAuth?: boolean, auth?: object } +interface AcquisitionContext { startTime?: number, forceReAuth?: boolean, skipReAuth?: boolean, auth?: object, triggerValidation?: boolean } interface ConstructorParam { create?: Create From 5318ccf6b536eebada9b836ff8c2275ac2f687c6 Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 11 Jun 2025 13:34:34 +0200 Subject: [PATCH 13/14] expect any number for start time --- .../connection-provider-routing.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js b/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js index 56602ddf6..2760c687c 100644 --- a/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js +++ b/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js @@ -3494,7 +3494,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalled() + expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server0) expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3536,7 +3536,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalled() + expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server0) expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3580,7 +3580,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalled() + expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server0) expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3609,7 +3609,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalled() + expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server0) expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) From 93698a157ffeac3128276a39e02dc77171bd31af Mon Sep 17 00:00:00 2001 From: MaxAake <61233757+MaxAake@users.noreply.github.com> Date: Wed, 11 Jun 2025 14:21:05 +0200 Subject: [PATCH 14/14] fix server number --- .../connection-provider/connection-provider-routing.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js b/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js index 2760c687c..c22f3462a 100644 --- a/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js +++ b/packages/bolt-connection/test/connection-provider/connection-provider-routing.test.js @@ -3494,7 +3494,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server0) + expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server3) expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) }) @@ -3536,7 +3536,7 @@ describe.each([ .catch(functional.identity) expect(error).toEqual(newError('Driver is connected to a database that does not support user switch.')) - expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server0) + expect(poolAcquire).toHaveBeenCalledWith({ auth, startTime: expect.any(Number) }, server1) expect(connection.release).toHaveBeenCalled() expect(connection._sticky).toEqual(isStickyConn) })