386 lines
12 KiB
JavaScript
386 lines
12 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.WRITE = exports.READ = exports.Driver = undefined;
|
|
|
|
var _maxSafeInteger = require('babel-runtime/core-js/number/max-safe-integer');
|
|
|
|
var _maxSafeInteger2 = _interopRequireDefault(_maxSafeInteger);
|
|
|
|
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
|
|
|
|
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
|
|
|
|
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
|
|
|
|
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
|
|
|
|
var _get2 = require('babel-runtime/helpers/get');
|
|
|
|
var _get3 = _interopRequireDefault(_get2);
|
|
|
|
var _inherits2 = require('babel-runtime/helpers/inherits');
|
|
|
|
var _inherits3 = _interopRequireDefault(_inherits2);
|
|
|
|
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
|
|
|
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
|
|
|
var _createClass2 = require('babel-runtime/helpers/createClass');
|
|
|
|
var _createClass3 = _interopRequireDefault(_createClass2);
|
|
|
|
var _session = require('./session');
|
|
|
|
var _session2 = _interopRequireDefault(_session);
|
|
|
|
var _pool = require('./internal/pool');
|
|
|
|
var _pool2 = _interopRequireDefault(_pool);
|
|
|
|
var _connector = require('./internal/connector');
|
|
|
|
var _streamObserver = require('./internal/stream-observer');
|
|
|
|
var _streamObserver2 = _interopRequireDefault(_streamObserver);
|
|
|
|
var _error = require('./error');
|
|
|
|
var _connectionProviders = require('./internal/connection-providers');
|
|
|
|
var _bookmark = require('./internal/bookmark');
|
|
|
|
var _bookmark2 = _interopRequireDefault(_bookmark);
|
|
|
|
var _connectivityVerifier = require('./internal/connectivity-verifier');
|
|
|
|
var _connectivityVerifier2 = _interopRequireDefault(_connectivityVerifier);
|
|
|
|
var _poolConfig = require('./internal/pool-config');
|
|
|
|
var _poolConfig2 = _interopRequireDefault(_poolConfig);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
var DEFAULT_MAX_CONNECTION_LIFETIME = 60 * 60 * 1000; // 1 hour
|
|
|
|
/**
|
|
* Constant that represents read session access mode.
|
|
* Should be used like this: <code>driver.session(READ)</code>.
|
|
* @type {string}
|
|
*/
|
|
/**
|
|
* 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 READ = 'READ';
|
|
|
|
/**
|
|
* Constant that represents write session access mode.
|
|
* Should be used like this: <code>driver.session(WRITE)</code>.
|
|
* @type {string}
|
|
*/
|
|
var WRITE = 'WRITE';
|
|
|
|
/**
|
|
* A driver maintains one or more {@link Session}s with a remote
|
|
* Neo4j instance. Through the {@link Session}s you can send statements
|
|
* and retrieve results from the database.
|
|
*
|
|
* Drivers are reasonably expensive to create - you should strive to keep one
|
|
* driver instance around per Neo4j Instance you connect to.
|
|
*
|
|
* @access public
|
|
*/
|
|
|
|
var Driver = function () {
|
|
/**
|
|
* You should not be calling this directly, instead use {@link driver}.
|
|
* @constructor
|
|
* @param {string} hostPort
|
|
* @param {string} userAgent
|
|
* @param {object} token
|
|
* @param {object} config
|
|
* @protected
|
|
*/
|
|
function Driver(hostPort, userAgent) {
|
|
var token = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
(0, _classCallCheck3.default)(this, Driver);
|
|
|
|
sanitizeConfig(config);
|
|
|
|
this._hostPort = hostPort;
|
|
this._userAgent = userAgent;
|
|
this._openSessions = {};
|
|
this._sessionIdGenerator = 0;
|
|
this._token = token;
|
|
this._config = config;
|
|
this._pool = new _pool2.default(this._createConnection.bind(this), this._destroyConnection.bind(this), this._validateConnection.bind(this), _poolConfig2.default.fromDriverConfig(config));
|
|
|
|
/**
|
|
* Reference to the connection provider. Initialized lazily by {@link _getOrCreateConnectionProvider}.
|
|
* @type {ConnectionProvider}
|
|
* @protected
|
|
*/
|
|
this._connectionProvider = null;
|
|
|
|
this._onCompleted = null;
|
|
}
|
|
|
|
/**
|
|
* Get the installed connectivity verification callback.
|
|
* @return {null|function}
|
|
* @deprecated driver can be used directly once instantiated, use of this callback is not required.
|
|
*/
|
|
|
|
|
|
(0, _createClass3.default)(Driver, [{
|
|
key: '_createConnection',
|
|
|
|
|
|
/**
|
|
* Create a new connection instance.
|
|
* @return {Connection} new connector-api session instance, a low level session API.
|
|
* @access private
|
|
*/
|
|
value: function _createConnection(hostPort, release) {
|
|
var sessionId = this._sessionIdGenerator++;
|
|
var conn = (0, _connector.connect)(hostPort, this._config, this._connectionErrorCode());
|
|
var streamObserver = new _ConnectionStreamObserver(this, conn);
|
|
conn.initialize(this._userAgent, this._token, streamObserver);
|
|
conn._id = sessionId;
|
|
conn._release = function () {
|
|
return release(hostPort, conn);
|
|
};
|
|
|
|
this._openSessions[sessionId] = conn;
|
|
return conn;
|
|
}
|
|
|
|
/**
|
|
* Check that a connection is usable
|
|
* @return {boolean} true if the connection is open
|
|
* @access private
|
|
**/
|
|
|
|
}, {
|
|
key: '_validateConnection',
|
|
value: function _validateConnection(conn) {
|
|
if (!conn.isOpen()) {
|
|
return false;
|
|
}
|
|
|
|
var maxConnectionLifetime = this._config.maxConnectionLifetime;
|
|
var lifetime = Date.now() - conn.creationTimestamp;
|
|
return lifetime <= maxConnectionLifetime;
|
|
}
|
|
|
|
/**
|
|
* Dispose of a live session, closing any associated resources.
|
|
* @return {Session} new session.
|
|
* @access private
|
|
*/
|
|
|
|
}, {
|
|
key: '_destroyConnection',
|
|
value: function _destroyConnection(conn) {
|
|
delete this._openSessions[conn._id];
|
|
conn.close();
|
|
}
|
|
|
|
/**
|
|
* Acquire a session to communicate with the database. The driver maintains
|
|
* a pool of sessions, so calling this method is normally cheap because you
|
|
* will be pulling a session out of the common pool.
|
|
*
|
|
* This comes with some responsibility - make sure you always call
|
|
* {@link close} when you are done using a session, and likewise,
|
|
* make sure you don't close your session before you are done using it. Once
|
|
* it is returned to the pool, the session will be reset to a clean state and
|
|
* made available for others to use.
|
|
*
|
|
* @param {string} [mode=WRITE] the access mode of this session, allowed values are {@link READ} and {@link WRITE}.
|
|
* @param {string|string[]} [bookmarkOrBookmarks=null] the initial reference or references to some previous
|
|
* transactions. Value is optional and absence indicates that that the bookmarks do not exist or are unknown.
|
|
* @return {Session} new session.
|
|
*/
|
|
|
|
}, {
|
|
key: 'session',
|
|
value: function session(mode, bookmarkOrBookmarks) {
|
|
var sessionMode = Driver._validateSessionMode(mode);
|
|
var connectionProvider = this._getOrCreateConnectionProvider();
|
|
var bookmark = new _bookmark2.default(bookmarkOrBookmarks);
|
|
return this._createSession(sessionMode, connectionProvider, bookmark, this._config);
|
|
}
|
|
}, {
|
|
key: '_createConnectionProvider',
|
|
|
|
|
|
// Extension point
|
|
value: function _createConnectionProvider(hostPort, connectionPool, driverOnErrorCallback) {
|
|
return new _connectionProviders.DirectConnectionProvider(hostPort, connectionPool, driverOnErrorCallback);
|
|
}
|
|
|
|
// Extension point
|
|
|
|
}, {
|
|
key: '_createSession',
|
|
value: function _createSession(mode, connectionProvider, bookmark, config) {
|
|
return new _session2.default(mode, connectionProvider, bookmark, config);
|
|
}
|
|
|
|
// Extension point
|
|
|
|
}, {
|
|
key: '_connectionErrorCode',
|
|
value: function _connectionErrorCode() {
|
|
// connection errors might result in different error codes depending on the driver
|
|
return _error.SERVICE_UNAVAILABLE;
|
|
}
|
|
}, {
|
|
key: '_getOrCreateConnectionProvider',
|
|
value: function _getOrCreateConnectionProvider() {
|
|
if (!this._connectionProvider) {
|
|
var driverOnErrorCallback = this._driverOnErrorCallback.bind(this);
|
|
this._connectionProvider = this._createConnectionProvider(this._hostPort, this._pool, driverOnErrorCallback);
|
|
}
|
|
return this._connectionProvider;
|
|
}
|
|
}, {
|
|
key: '_driverOnErrorCallback',
|
|
value: function _driverOnErrorCallback(error) {
|
|
var userDefinedOnErrorCallback = this.onError;
|
|
if (userDefinedOnErrorCallback && error.code === _error.SERVICE_UNAVAILABLE) {
|
|
userDefinedOnErrorCallback(error);
|
|
} else {
|
|
// we don't need to tell the driver about this error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close all open sessions and other associated resources. You should
|
|
* make sure to use this when you are done with this driver instance.
|
|
* @return undefined
|
|
*/
|
|
|
|
}, {
|
|
key: 'close',
|
|
value: function close() {
|
|
for (var sessionId in this._openSessions) {
|
|
if (this._openSessions.hasOwnProperty(sessionId)) {
|
|
this._openSessions[sessionId].close();
|
|
}
|
|
this._pool.purgeAll();
|
|
}
|
|
}
|
|
}, {
|
|
key: 'onCompleted',
|
|
get: function get() {
|
|
return this._onCompleted;
|
|
}
|
|
|
|
/**
|
|
* Install a connectivity verification callback.
|
|
* @param {null|function} callback the new function to be notified about successful connection.
|
|
* @deprecated driver can be used directly once instantiated, use of this callback is not required.
|
|
*/
|
|
,
|
|
set: function set(callback) {
|
|
this._onCompleted = callback;
|
|
if (this._onCompleted) {
|
|
var connectionProvider = this._getOrCreateConnectionProvider();
|
|
var connectivityVerifier = new _connectivityVerifier2.default(connectionProvider, this._onCompleted);
|
|
connectivityVerifier.verify();
|
|
}
|
|
}
|
|
}], [{
|
|
key: '_validateSessionMode',
|
|
value: function _validateSessionMode(rawMode) {
|
|
var mode = rawMode || WRITE;
|
|
if (mode !== READ && mode !== WRITE) {
|
|
throw (0, _error.newError)('Illegal session mode ' + mode);
|
|
}
|
|
return mode;
|
|
}
|
|
}]);
|
|
return Driver;
|
|
}();
|
|
|
|
/** Internal stream observer used for connection state */
|
|
|
|
|
|
var _ConnectionStreamObserver = function (_StreamObserver) {
|
|
(0, _inherits3.default)(_ConnectionStreamObserver, _StreamObserver);
|
|
|
|
function _ConnectionStreamObserver(driver, conn) {
|
|
(0, _classCallCheck3.default)(this, _ConnectionStreamObserver);
|
|
|
|
var _this = (0, _possibleConstructorReturn3.default)(this, (_ConnectionStreamObserver.__proto__ || (0, _getPrototypeOf2.default)(_ConnectionStreamObserver)).call(this));
|
|
|
|
_this._driver = driver;
|
|
_this._conn = conn;
|
|
_this._hasFailed = false;
|
|
return _this;
|
|
}
|
|
|
|
(0, _createClass3.default)(_ConnectionStreamObserver, [{
|
|
key: 'onError',
|
|
value: function onError(error) {
|
|
if (!this._hasFailed) {
|
|
(0, _get3.default)(_ConnectionStreamObserver.prototype.__proto__ || (0, _getPrototypeOf2.default)(_ConnectionStreamObserver.prototype), 'onError', this).call(this, error);
|
|
if (this._driver.onError) {
|
|
this._driver.onError(error);
|
|
}
|
|
this._hasFailed = true;
|
|
}
|
|
}
|
|
}]);
|
|
return _ConnectionStreamObserver;
|
|
}(_streamObserver2.default);
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
|
|
function sanitizeConfig(config) {
|
|
config.maxConnectionLifetime = sanitizeIntValue(config.maxConnectionLifetime, DEFAULT_MAX_CONNECTION_LIFETIME);
|
|
config.maxConnectionPoolSize = sanitizeIntValue(config.maxConnectionPoolSize, _poolConfig.DEFAULT_MAX_SIZE);
|
|
config.connectionAcquisitionTimeout = sanitizeIntValue(config.connectionAcquisitionTimeout, _poolConfig.DEFAULT_ACQUISITION_TIMEOUT);
|
|
}
|
|
|
|
function sanitizeIntValue(rawValue, defaultWhenAbsent) {
|
|
var sanitizedValue = parseInt(rawValue, 10);
|
|
if (sanitizedValue > 0 || sanitizedValue === 0) {
|
|
return sanitizedValue;
|
|
} else if (sanitizedValue < 0) {
|
|
return _maxSafeInteger2.default;
|
|
} else {
|
|
return defaultWhenAbsent;
|
|
}
|
|
}
|
|
|
|
exports.Driver = Driver;
|
|
exports.READ = READ;
|
|
exports.WRITE = WRITE;
|
|
exports.default = Driver; |