diff --git a/src/driver.js b/src/driver.js index f2b4c6b10..98dc3fa60 100644 --- a/src/driver.js +++ b/src/driver.js @@ -19,8 +19,9 @@ import ConnectionProvider from './internal/connection-provider' import Bookmark from './internal/bookmark' -import DirectConnectionProvider from './internal/connection-provider-direct' import ConnectivityVerifier from './internal/connectivity-verifier' +import ConfiguredCustomResolver from './internal/resolver/configured-custom-resolver' + import { ACCESS_MODE_READ, ACCESS_MODE_WRITE, @@ -74,20 +75,23 @@ class Driver { * You should not be calling this directly, instead use {@link driver}. * @constructor * @protected - * @param {ServerAddress} address - * @param {string} userAgent - * @param {Object} authToken + * @param {Object} meta Metainformation about the driver * @param {Object} config + * @param {function(id: number, config:Object, log:Logger, hostNameResolver: ConfiguredCustomResolver): ConnectionProvider } createConnectonProvider Creates the connection provider */ - constructor (address, userAgent, authToken = {}, config = {}) { + constructor ( + meta, + config = {}, + createConnectonProvider = (id, config, log, hostNameResolver) => {} + ) { sanitizeConfig(config) + validateConfig(config) this._id = idGenerator++ - this._address = address - this._userAgent = userAgent - this._authToken = authToken + this._meta = meta this._config = config this._log = Logger.create(config) + this._createConnectionProvider = createConnectonProvider /** * Reference to the connection provider. Initialized lazily by {@link _getOrCreateConnectionProvider}. @@ -144,7 +148,7 @@ class Driver { * @returns {boolean} */ _supportsRouting () { - return false + return this._meta.routing } /** @@ -259,24 +263,10 @@ class Driver { */ _afterConstruction () { this._log.info( - `Direct driver ${this._id} created for server address ${this._address}` + `${this._meta.typename} driver ${this._id} created for server address ${this._meta.address}` ) } - /** - * @protected - */ - _createConnectionProvider (address, userAgent, authToken) { - return new DirectConnectionProvider({ - id: this._id, - config: this._config, - log: this._log, - address: address, - userAgent: userAgent, - authToken: authToken - }) - } - /** * @private */ @@ -309,9 +299,10 @@ class Driver { _getOrCreateConnectionProvider () { if (!this._connectionProvider) { this._connectionProvider = this._createConnectionProvider( - this._address, - this._userAgent, - this._authToken + this._id, + this._config, + this._log, + createHostNameResolver(this._config) ) } @@ -319,6 +310,20 @@ class Driver { } } +/** + * @private + * @returns {Object} the given config. + */ +function validateConfig (config) { + const resolver = config.resolver + if (resolver && typeof resolver !== 'function') { + throw new TypeError( + `Configured resolver should be a function. Got: ${resolver}` + ) + } + return config +} + /** * @private */ @@ -371,6 +376,15 @@ function validateFetchSizeValue (rawValue, defaultWhenAbsent) { } } +/** + * @private + * @returns {ConfiguredCustomResolver} new custom resolver that wraps the passed-in resolver function. + * If resolved function is not specified, it defaults to an identity resolver. + */ +function createHostNameResolver (config) { + return new ConfiguredCustomResolver(config.resolver) +} + export { Driver, READ, WRITE } export default Driver diff --git a/src/index.js b/src/index.js index bca5fd952..8f9223bf3 100644 --- a/src/index.js +++ b/src/index.js @@ -17,7 +17,6 @@ * limitations under the License. */ import { Driver, READ, WRITE } from './driver' -import RoutingDriver from './routing-driver' import VERSION from './version' import urlUtil from './internal/url-util' import ServerAddress from './internal/server-address' @@ -55,6 +54,9 @@ import { ResultSummary, Result } from 'neo4j-driver-core' +import { HostNameResolver } from './internal/node' +import DirectConnectionProvider from './internal/connection-provider-direct' +import RoutingConnectionProvider from './internal/connection-provider-routing' const { util: { ENCRYPTION_ON, ENCRYPTION_OFF, assertString, isEmptyObjectOrNull } @@ -236,27 +238,46 @@ function driver (url, authToken, config = {}) { // Use default user agent or user agent specified by user. config.userAgent = config.userAgent || USER_AGENT + const address = ServerAddress.fromUrl(parsedUrl.hostAndPort) - if (routing) { - return new RoutingDriver( - ServerAddress.fromUrl(parsedUrl.hostAndPort), - parsedUrl.query, - config.userAgent, - authToken, - config - ) - } else { - if (!isEmptyObjectOrNull(parsedUrl.query)) { - throw new Error( - `Parameters are not supported with none routed scheme. Given URL: '${url}'` - ) + const meta = { + address, + typename: routing ? 'Routing' : 'Direct', + routing + } + + return new Driver(meta, config, createConnectionProviderFunction()) + + function createConnectionProviderFunction () { + if (routing) { + return (id, config, log, hostNameResolver) => + new RoutingConnectionProvider({ + id, + config, + log, + hostNameResolver, + authToken, + address, + userAgent: config.userAgent, + routingContext: parsedUrl.query + }) + } else { + if (!isEmptyObjectOrNull(parsedUrl.query)) { + throw new Error( + `Parameters are not supported with none routed scheme. Given URL: '${url}'` + ) + } + + return (id, config, log) => + new DirectConnectionProvider({ + id, + config, + log, + authToken, + address, + userAgent: config.userAgent + }) } - return new Driver( - ServerAddress.fromUrl(parsedUrl.hostAndPort), - config.userAgent, - authToken, - config - ) } } diff --git a/src/routing-driver.js b/src/routing-driver.js deleted file mode 100644 index 6e9c382b0..000000000 --- a/src/routing-driver.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Driver } from './driver' -import RoutingConnectionProvider from './internal/connection-provider-routing' -import ConfiguredCustomResolver from './internal/resolver/configured-custom-resolver' - -/** - * A driver that supports routing in a causal cluster. - * @private - */ -class RoutingDriver extends Driver { - constructor (address, routingContext, userAgent, token = {}, config = {}) { - super(address, userAgent, token, validateConfig(config)) - this._routingContext = routingContext - } - - _afterConstruction () { - this._log.info( - `Routing driver ${this._id} created for server address ${this._address}` - ) - } - - _createConnectionProvider (address, userAgent, authToken) { - return new RoutingConnectionProvider({ - id: this._id, - address: address, - routingContext: this._routingContext, - hostNameResolver: createHostNameResolver(this._config), - config: this._config, - log: this._log, - userAgent: userAgent, - authToken: authToken - }) - } - - _supportsRouting () { - return true - } -} - -/** - * @private - * @returns {ConfiguredCustomResolver} new custom resolver that wraps the passed-in resolver function. - * If resolved function is not specified, it defaults to an identity resolver. - */ -function createHostNameResolver (config) { - return new ConfiguredCustomResolver(config.resolver) -} - -/** - * @private - * @returns {Object} the given config. - */ -function validateConfig (config) { - const resolver = config.resolver - if (resolver && typeof resolver !== 'function') { - throw new TypeError( - `Configured resolver should be a function. Got: ${resolver}` - ) - } - return config -} - -export default RoutingDriver