From 1c0959b8af6af1e4ae2152097c8c5949c67f1e81 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Mon, 1 Nov 2021 17:37:26 +0100 Subject: [PATCH 1/2] Handle AuthorizationExpired during rediscovery The connections to a server should not be sent back to the pool if an AuthenticationExpired failure happens. Sending the connection back to the pool will make the next work using the connection fails with the same error. --- .../connection-provider/connection-provider-routing.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 7646abd6c..0dbe88b26 100644 --- a/packages/bolt-connection/src/connection-provider/connection-provider-routing.js +++ b/packages/bolt-connection/src/connection-provider/connection-provider-routing.js @@ -477,7 +477,14 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider async _createSessionForRediscovery (routerAddress, bookmark, impersonatedUser) { try { const connection = await this._connectionPool.acquire(routerAddress) - const connectionProvider = new SingleConnectionProvider(connection) + + const databaseSpecificErrorHandler = ConnectionErrorHandler.create({ + errorCode: SESSION_EXPIRED, + handleAuthorizationExpired: (error, address) => this._handleAuthorizationExpired(error, address) + }) + + const connectionProvider = new SingleConnectionProvider( + new DelegateConnection(connection, databaseSpecificErrorHandler)) const protocolVersion = connection.protocol().version if (protocolVersion < 4.0) { From c7c14249fdb49ba53692dab560ea1959c788eb51 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 2 Nov 2021 12:38:38 +0100 Subject: [PATCH 2/2] stress-test: always wait for bm when isCluster --- .../test/internal/shared-neo4j.js | 12 +++++++++-- packages/neo4j-driver/test/stress-test.js | 20 +++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index 84a3f40ad..dde00c2a9 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -308,18 +308,25 @@ function restart (configOverride) { startNeo4j() } -async function cleanupAndGetProtocolVersion (driver) { +async function cleanupAndGetProtocolVersionAndBookmark (driver) { const session = driver.session({ defaultAccessMode: neo4j.session.WRITE }) try { const result = await session.writeTransaction(tx => tx.run('MATCH (n) DETACH DELETE n') ) - return result.summary.server.protocolVersion + return [result.summary.server.protocolVersion, session.lastBookmark()] } finally { await session.close() } } +async function cleanupAndGetProtocolVersion (driver) { + const [protocolVersion] = await cleanupAndGetProtocolVersionAndBookmark( + driver + ) + return protocolVersion +} + async function getEdition (driver) { const session = driver.session({ defaultAccessMode: neo4j.session.READ }) try { @@ -375,6 +382,7 @@ export default { authToken: authToken, logging: debugLogging, cleanupAndGetProtocolVersion: cleanupAndGetProtocolVersion, + cleanupAndGetProtocolVersionAndBookmark, tlsConfig: tlsConfig, getEdition: getEdition, hostname: hostname, diff --git a/packages/neo4j-driver/test/stress-test.js b/packages/neo4j-driver/test/stress-test.js index 8ecd19487..a88f245e9 100644 --- a/packages/neo4j-driver/test/stress-test.js +++ b/packages/neo4j-driver/test/stress-test.js @@ -74,7 +74,10 @@ export default async function execute () { neo4j.auth.basic(USERNAME, PASSWORD), config ) - const protocolVersion = await sharedNeo4j.cleanupAndGetProtocolVersion(driver) + const [ + protocolVersion, + bookmarks + ] = await sharedNeo4j.cleanupAndGetProtocolVersionAndBookmark(driver) console.time('Basic-stress-test') const printStats = () => { console.timeEnd('Basic-stress-test') @@ -83,7 +86,12 @@ export default async function execute () { console.log('Write statistics: ', context.writeServersWithQueryCount) } - const context = new Context(driver, LOGGING_ENABLED, protocolVersion) + const context = new Context( + driver, + LOGGING_ENABLED, + protocolVersion, + bookmarks + ) try { await runWhileNotTimeout(async () => { @@ -525,10 +533,10 @@ function noParams () { } function newSession (context, accessMode, useBookmark) { - if (useBookmark) { + if (useBookmark || isCluster()) { return context.driver.session({ defaultAccessMode: accessMode, - bookmarks: [context.bookmark] + bookmarks: context.bookmark }) } return context.driver.session({ defaultAccessMode: accessMode }) @@ -556,9 +564,9 @@ function arraysEqual (array1, array2) { } class Context { - constructor (driver, loggingEnabled, protocolVersion) { + constructor (driver, loggingEnabled, protocolVersion, bookmark) { this.driver = driver - this.bookmark = null + this.bookmark = bookmark this.createdNodesCount = 0 this._commandIdCouter = 0 this._loggingEnabled = loggingEnabled