'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _session = require('./session'); var _session2 = _interopRequireDefault(_session); var _driver = require('./driver'); var _error = require('./error'); var _connectionProviders = require('./internal/connection-providers'); var _leastConnectedLoadBalancingStrategy = require('./internal/least-connected-load-balancing-strategy'); var _leastConnectedLoadBalancingStrategy2 = _interopRequireDefault(_leastConnectedLoadBalancingStrategy); var _roundRobinLoadBalancingStrategy = require('./internal/round-robin-load-balancing-strategy'); var _roundRobinLoadBalancingStrategy2 = _interopRequireDefault(_roundRobinLoadBalancingStrategy); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * A driver that supports routing in a causal cluster. * @private */ /** * Copyright (c) 2002-2018 "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. */ var RoutingDriver = function (_Driver) { (0, _inherits3.default)(RoutingDriver, _Driver); function RoutingDriver(hostPort, routingContext, userAgent) { var token = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; var config = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; (0, _classCallCheck3.default)(this, RoutingDriver); var _this = (0, _possibleConstructorReturn3.default)(this, (RoutingDriver.__proto__ || (0, _getPrototypeOf2.default)(RoutingDriver)).call(this, hostPort, userAgent, token, validateConfig(config))); _this._routingContext = routingContext; return _this; } (0, _createClass3.default)(RoutingDriver, [{ key: '_createConnectionProvider', value: function _createConnectionProvider(hostPort, connectionPool, driverOnErrorCallback) { var loadBalancingStrategy = RoutingDriver._createLoadBalancingStrategy(this._config, connectionPool); return new _connectionProviders.LoadBalancer(hostPort, this._routingContext, connectionPool, loadBalancingStrategy, driverOnErrorCallback); } }, { key: '_createSession', value: function _createSession(mode, connectionProvider, bookmark, config) { var _this2 = this; return new RoutingSession(mode, connectionProvider, bookmark, config, function (error, conn) { if (!conn) { // connection can be undefined if error happened before connection was acquired return error; } var hostPort = conn.hostPort; if (error.code === _error.SESSION_EXPIRED || isDatabaseUnavailable(error)) { _this2._connectionProvider.forget(hostPort); return error; } else if (isFailureToWrite(error)) { _this2._connectionProvider.forgetWriter(hostPort); return (0, _error.newError)('No longer possible to write to server at ' + hostPort, _error.SESSION_EXPIRED); } else { return error; } }); } }, { key: '_connectionErrorCode', value: function _connectionErrorCode() { // connection errors mean SERVICE_UNAVAILABLE for direct driver but for routing driver they should only // result in SESSION_EXPIRED because there might still exist other servers capable of serving the request return _error.SESSION_EXPIRED; } /** * Create new load balancing strategy based on the config. * @param {object} config the user provided config. * @param {Pool} connectionPool the connection pool for this driver. * @return {LoadBalancingStrategy} new strategy. * @private */ }], [{ key: '_createLoadBalancingStrategy', value: function _createLoadBalancingStrategy(config, connectionPool) { var configuredValue = config.loadBalancingStrategy; if (!configuredValue || configuredValue === _leastConnectedLoadBalancingStrategy.LEAST_CONNECTED_STRATEGY_NAME) { return new _leastConnectedLoadBalancingStrategy2.default(connectionPool); } else if (configuredValue === _roundRobinLoadBalancingStrategy.ROUND_ROBIN_STRATEGY_NAME) { return new _roundRobinLoadBalancingStrategy2.default(); } else { throw (0, _error.newError)('Unknown load balancing strategy: ' + configuredValue); } } }]); return RoutingDriver; }(_driver.Driver); /** * @private */ function validateConfig(config) { if (config.trust === 'TRUST_ON_FIRST_USE') { throw (0, _error.newError)('The chosen trust mode is not compatible with a routing driver'); } return config; } /** * @private */ function isFailureToWrite(error) { return error.code === 'Neo.ClientError.Cluster.NotALeader' || error.code === 'Neo.ClientError.General.ForbiddenOnReadOnlyDatabase'; } /** * @private */ function isDatabaseUnavailable(error) { return error.code === 'Neo.TransientError.General.DatabaseUnavailable'; } /** * @private */ var RoutingSession = function (_Session) { (0, _inherits3.default)(RoutingSession, _Session); function RoutingSession(mode, connectionProvider, bookmark, config, onFailedConnection) { (0, _classCallCheck3.default)(this, RoutingSession); var _this3 = (0, _possibleConstructorReturn3.default)(this, (RoutingSession.__proto__ || (0, _getPrototypeOf2.default)(RoutingSession)).call(this, mode, connectionProvider, bookmark, config)); _this3._onFailedConnection = onFailedConnection; return _this3; } (0, _createClass3.default)(RoutingSession, [{ key: '_onRunFailure', value: function _onRunFailure() { return this._onFailedConnection; } }]); return RoutingSession; }(_session2.default); exports.default = RoutingDriver;