Skip to content

Commit 17cd66f

Browse files
committed
Merge branch '5.0' into testkit-frontend-error
2 parents bdd014e + 5ef3add commit 17cd66f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2143
-458
lines changed

packages/bolt-connection/src/channel/channel-config.js

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ const {
2525

2626
const { SERVICE_UNAVAILABLE } = error
2727

28-
const DEFAULT_CONNECTION_TIMEOUT_MILLIS = 30000 // 30 seconds by default
29-
3028
const ALLOWED_VALUES_ENCRYPTED = [
3129
null,
3230
undefined,
@@ -58,7 +56,7 @@ export default class ChannelConfig {
5856
this.trustedCertificates = extractTrustedCertificates(driverConfig)
5957
this.knownHostsPath = extractKnownHostsPath(driverConfig)
6058
this.connectionErrorCode = connectionErrorCode || SERVICE_UNAVAILABLE
61-
this.connectionTimeout = extractConnectionTimeout(driverConfig)
59+
this.connectionTimeout = driverConfig.connectionTimeout
6260
}
6361
}
6462

@@ -90,19 +88,3 @@ function extractKnownHostsPath (driverConfig) {
9088
return driverConfig.knownHosts || null
9189
}
9290

93-
function extractConnectionTimeout (driverConfig) {
94-
const configuredTimeout = parseInt(driverConfig.connectionTimeout, 10)
95-
if (configuredTimeout === 0) {
96-
// timeout explicitly configured to 0
97-
return null
98-
} else if (configuredTimeout && configuredTimeout < 0) {
99-
// timeout explicitly configured to a negative value
100-
return null
101-
} else if (!configuredTimeout) {
102-
// timeout not configured, use default value
103-
return DEFAULT_CONNECTION_TIMEOUT_MILLIS
104-
} else {
105-
// timeout configured, use the provided value
106-
return configuredTimeout
107-
}
108-
}

packages/bolt-connection/src/connection-provider/connection-provider-direct.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,8 @@ export default class DirectConnectionProvider extends PooledConnectionProvider {
103103
version => version >= BOLT_PROTOCOL_V4_4
104104
)
105105
}
106+
107+
async verifyConnectivityAndGetServerInfo () {
108+
return await this._verifyConnectivityAndGetServerVersion({ address: this._address })
109+
}
106110
}

packages/bolt-connection/src/connection-provider/connection-provider-pooled.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import { createChannelConnection, ConnectionErrorHandler } from '../connection'
2121
import Pool, { PoolConfig } from '../pool'
22-
import { error, ConnectionProvider } from 'neo4j-driver-core'
22+
import { error, ConnectionProvider, ServerInfo } from 'neo4j-driver-core'
2323

2424
const { SERVICE_UNAVAILABLE } = error
2525
export default class PooledConnectionProvider extends ConnectionProvider {
@@ -109,6 +109,23 @@ export default class PooledConnectionProvider extends ConnectionProvider {
109109
return conn.close()
110110
}
111111

112+
/**
113+
* Acquire a connection from the pool and return it ServerInfo
114+
* @param {object} param
115+
* @param {string} param.address the server address
116+
* @return {Promise<ServerInfo>} the server info
117+
*/
118+
async _verifyConnectivityAndGetServerVersion ({ address }) {
119+
const connection = await this._connectionPool.acquire(address)
120+
const serverInfo = new ServerInfo(connection.server, connection.protocol().version)
121+
try {
122+
await connection.resetAndFlush()
123+
} finally {
124+
await connection._release()
125+
}
126+
return serverInfo
127+
}
128+
112129
async close () {
113130
// purge all idle connections in the connection pool
114131
await this._connectionPool.close()

packages/bolt-connection/src/connection-provider/connection-provider-routing.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,24 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider
237237
return await this._hasProtocolVersion(
238238
version => version >= BOLT_PROTOCOL_V4_4
239239
)
240-
}
240+
}
241+
242+
async verifyConnectivityAndGetServerInfo ({ database, accessMode }) {
243+
const context = { database: database || DEFAULT_DB_NAME }
244+
245+
const routingTable = await this._freshRoutingTable({
246+
accessMode,
247+
database: context.database,
248+
onDatabaseNameResolved: (databaseName) => {
249+
context.database = context.database || databaseName
250+
}
251+
})
252+
253+
const servers = accessMode === WRITE ? routingTable.writers : routingTable.readers
254+
255+
return Promise.all(servers.map(address => this._verifyConnectivityAndGetServerVersion({ address })))
256+
.then(([serverInfo]) => serverInfo)
257+
}
241258

242259
forget (address, database) {
243260
this._routingTableRegistry.apply(database, {

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

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -71,54 +71,48 @@ class Pool {
7171
/**
7272
* Acquire and idle resource fom the pool or create a new one.
7373
* @param {ServerAddress} address the address for which we're acquiring.
74-
* @return {Object} resource that is ready to use.
74+
* @return {Promise<Object>} resource that is ready to use.
7575
*/
7676
acquire (address) {
77-
return this._acquire(address).then(resource => {
78-
const key = address.asKey()
77+
const key = address.asKey()
7978

80-
if (resource) {
81-
// New or existing resource acquired
82-
return resource
83-
}
79+
// We're out of resources and will try to acquire later on when an existing resource is released.
80+
const allRequests = this._acquireRequests
81+
const requests = allRequests[key]
82+
if (!requests) {
83+
allRequests[key] = []
84+
}
85+
return new Promise((resolve, reject) => {
86+
let request
8487

85-
// We're out of resources and will try to acquire later on when an existing resource is released.
86-
const allRequests = this._acquireRequests
87-
const requests = allRequests[key]
88-
if (!requests) {
89-
allRequests[key] = []
90-
}
88+
const timeoutId = setTimeout(() => {
89+
// acquisition timeout fired
9190

92-
return new Promise((resolve, reject) => {
93-
let request
94-
95-
const timeoutId = setTimeout(() => {
96-
// acquisition timeout fired
97-
98-
// remove request from the queue of pending requests, if it's still there
99-
// request might've been taken out by the release operation
100-
const pendingRequests = allRequests[key]
101-
if (pendingRequests) {
102-
allRequests[key] = pendingRequests.filter(item => item !== request)
103-
}
104-
105-
if (request.isCompleted()) {
106-
// request already resolved/rejected by the release operation; nothing to do
107-
} else {
108-
// request is still pending and needs to be failed
109-
const activeCount = this.activeResourceCount(address)
110-
const idleCount = this.has(address) ? this._pools[key].length : 0
111-
request.reject(
112-
newError(
113-
`Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.`
114-
)
91+
// remove request from the queue of pending requests, if it's still there
92+
// request might've been taken out by the release operation
93+
const pendingRequests = allRequests[key]
94+
if (pendingRequests) {
95+
allRequests[key] = pendingRequests.filter(item => item !== request)
96+
}
97+
98+
if (request.isCompleted()) {
99+
// request already resolved/rejected by the release operation; nothing to do
100+
} else {
101+
// request is still pending and needs to be failed
102+
const activeCount = this.activeResourceCount(address)
103+
const idleCount = this.has(address) ? this._pools[key].length : 0
104+
request.reject(
105+
newError(
106+
`Connection acquisition timed out in ${this._acquisitionTimeout} ms. Pool status: Active conn count = ${activeCount}, Idle conn count = ${idleCount}.`
115107
)
116-
}
117-
}, this._acquisitionTimeout)
108+
)
109+
}
110+
}, this._acquisitionTimeout)
118111

119-
request = new PendingRequest(key, resolve, reject, timeoutId, this._log)
120-
allRequests[key].push(request)
121-
})
112+
request = new PendingRequest(key, resolve, reject, timeoutId, this._log)
113+
allRequests[key].push(request)
114+
115+
this._processPendingAcquireRequests(address)
122116
})
123117
}
124118

@@ -315,7 +309,7 @@ class Pool {
315309
_processPendingAcquireRequests (address) {
316310
const key = address.asKey()
317311
const requests = this._acquireRequests[key]
318-
const poolState = this._poolState[key]
312+
const poolState = this._poolState[key] || new PoolState()
319313
if (requests) {
320314
const pendingRequest = requests.shift() // pop a pending acquire request
321315

@@ -339,6 +333,15 @@ class Pool {
339333
// request is still pending and can be resolved with the newly acquired resource
340334
pendingRequest.resolve(resource) // resolve the pending request with the acquired resource
341335
}
336+
} else {
337+
// failed to acquire a valid resource from the pool
338+
// return the pending request back to the pool
339+
if (!pendingRequest.isCompleted()) {
340+
if (!this._acquireRequests[key]) {
341+
this._acquireRequests[key] = []
342+
}
343+
this._acquireRequests[key].unshift(pendingRequest)
344+
}
342345
}
343346
})
344347
} else {

packages/bolt-connection/test/channel/node/node-channel.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe('NodeChannel', () => {
110110
})
111111
})
112112

113-
function createMockedChannel (connected, config = {}) {
113+
function createMockedChannel (connected, config = { connectionTimeout: 30000 }) {
114114
let endCallback = null
115115
const address = ServerAddress.fromUrl('bolt://localhost:9999')
116116
const channelConfig = new ChannelConfig(address, config, SERVICE_UNAVAILABLE)

0 commit comments

Comments
 (0)