neo4j-driver-bolt-connection
Advanced tools
Comparing version 5.7.0 to 5.8.0
@@ -219,2 +219,3 @@ "use strict"; | ||
}); | ||
// TODO: Verify the Neo4j version in the message | ||
var error = (0, neo4j_driver_core_1.newError)('Driver is connected to a database that does not support logoff. ' + | ||
@@ -245,2 +246,3 @@ 'Please upgrade to Neo4j 5.5.0 or later in order to use this functionality.'); | ||
}); | ||
// TODO: Verify the Neo4j version in the message | ||
var error = (0, neo4j_driver_core_1.newError)('Driver is connected to a database that does not support logon. ' + | ||
@@ -247,0 +249,0 @@ 'Please upgrade to Neo4j 5.5.0 or later in order to use this functionality.'); |
@@ -78,3 +78,3 @@ "use strict"; | ||
var neo4j_driver_core_1 = require("neo4j-driver-core"); | ||
var _a = neo4j_driver_core_1.internal.constants, BOLT_PROTOCOL_V3 = _a.BOLT_PROTOCOL_V3, BOLT_PROTOCOL_V4_0 = _a.BOLT_PROTOCOL_V4_0, BOLT_PROTOCOL_V4_4 = _a.BOLT_PROTOCOL_V4_4; | ||
var _a = neo4j_driver_core_1.internal.constants, BOLT_PROTOCOL_V3 = _a.BOLT_PROTOCOL_V3, BOLT_PROTOCOL_V4_0 = _a.BOLT_PROTOCOL_V4_0, BOLT_PROTOCOL_V4_4 = _a.BOLT_PROTOCOL_V4_4, BOLT_PROTOCOL_V5_1 = _a.BOLT_PROTOCOL_V5_1; | ||
var SERVICE_UNAVAILABLE = neo4j_driver_core_1.error.SERVICE_UNAVAILABLE; | ||
@@ -84,4 +84,4 @@ var DirectConnectionProvider = /** @class */ (function (_super) { | ||
function DirectConnectionProvider(_a) { | ||
var id = _a.id, config = _a.config, log = _a.log, address = _a.address, userAgent = _a.userAgent, authToken = _a.authToken; | ||
var _this = _super.call(this, { id: id, config: config, log: log, userAgent: userAgent, authToken: authToken }) || this; | ||
var id = _a.id, config = _a.config, log = _a.log, address = _a.address, userAgent = _a.userAgent, authTokenManager = _a.authTokenManager, newPool = _a.newPool; | ||
var _this = _super.call(this, { id: id, config: config, log: log, userAgent: userAgent, authTokenManager: authTokenManager, newPool: newPool }) || this; | ||
_this._address = address; | ||
@@ -95,20 +95,35 @@ return _this; | ||
DirectConnectionProvider.prototype.acquireConnection = function (_a) { | ||
var _this = this; | ||
var _b = _a === void 0 ? {} : _a, accessMode = _b.accessMode, database = _b.database, bookmarks = _b.bookmarks; | ||
var databaseSpecificErrorHandler = connection_1.ConnectionErrorHandler.create({ | ||
errorCode: SERVICE_UNAVAILABLE, | ||
handleAuthorizationExpired: function (error, address) { | ||
return _this._handleAuthorizationExpired(error, address, database); | ||
} | ||
var _b = _a === void 0 ? {} : _a, accessMode = _b.accessMode, database = _b.database, bookmarks = _b.bookmarks, auth = _b.auth, forceReAuth = _b.forceReAuth; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var databaseSpecificErrorHandler, connection; | ||
var _this = this; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
databaseSpecificErrorHandler = connection_1.ConnectionErrorHandler.create({ | ||
errorCode: SERVICE_UNAVAILABLE, | ||
handleAuthorizationExpired: function (error, address, conn) { | ||
return _this._handleAuthorizationExpired(error, address, conn, database); | ||
} | ||
}); | ||
return [4 /*yield*/, this._connectionPool.acquire({ auth: auth, forceReAuth: forceReAuth }, this._address)]; | ||
case 1: | ||
connection = _c.sent(); | ||
if (!auth) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, this._verifyStickyConnection({ | ||
auth: auth, | ||
connection: connection, | ||
address: this._address | ||
})]; | ||
case 2: | ||
_c.sent(); | ||
return [2 /*return*/, connection]; | ||
case 3: return [2 /*return*/, new connection_1.DelegateConnection(connection, databaseSpecificErrorHandler)]; | ||
} | ||
}); | ||
}); | ||
return this._connectionPool | ||
.acquire(this._address) | ||
.then(function (connection) { | ||
return new connection_1.DelegateConnection(connection, databaseSpecificErrorHandler); | ||
}); | ||
}; | ||
DirectConnectionProvider.prototype._handleAuthorizationExpired = function (error, address, database) { | ||
DirectConnectionProvider.prototype._handleAuthorizationExpired = function (error, address, connection, database) { | ||
this._log.warn("Direct driver ".concat(this._id, " will close connection to ").concat(address, " for database '").concat(database, "' because of an error ").concat(error.code, " '").concat(error.message, "'")); | ||
this._connectionPool.purge(address).catch(function () { }); | ||
return error; | ||
return _super.prototype._handleAuthorizationExpired.call(this, error, address, connection); | ||
}; | ||
@@ -174,2 +189,24 @@ DirectConnectionProvider.prototype._hasProtocolVersion = function (versionPredicate) { | ||
}; | ||
DirectConnectionProvider.prototype.supportsSessionAuth = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this._hasProtocolVersion(function (version) { return version >= BOLT_PROTOCOL_V5_1; })]; | ||
case 1: return [2 /*return*/, _a.sent()]; | ||
} | ||
}); | ||
}); | ||
}; | ||
DirectConnectionProvider.prototype.verifyAuthentication = function (_a) { | ||
var auth = _a.auth; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_b) { | ||
return [2 /*return*/, this._verifyAuthentication({ | ||
auth: auth, | ||
getAddress: function () { return _this._address; } | ||
})]; | ||
}); | ||
}); | ||
}; | ||
DirectConnectionProvider.prototype.verifyConnectivityAndGetServerInfo = function () { | ||
@@ -176,0 +213,0 @@ return __awaiter(this, void 0, void 0, function () { |
@@ -94,2 +94,30 @@ "use strict"; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -99,7 +127,21 @@ var connection_1 = require("../connection"); | ||
var neo4j_driver_core_1 = require("neo4j-driver-core"); | ||
var authentication_provider_1 = __importDefault(require("./authentication-provider")); | ||
var lang_1 = require("../lang"); | ||
var SERVICE_UNAVAILABLE = neo4j_driver_core_1.error.SERVICE_UNAVAILABLE; | ||
var AUTHENTICATION_ERRORS = [ | ||
'Neo.ClientError.Security.CredentialsExpired', | ||
'Neo.ClientError.Security.Forbidden', | ||
'Neo.ClientError.Security.TokenExpired', | ||
'Neo.ClientError.Security.Unauthorized' | ||
]; | ||
var PooledConnectionProvider = /** @class */ (function (_super) { | ||
__extends(PooledConnectionProvider, _super); | ||
function PooledConnectionProvider(_a, createChannelConnectionHook) { | ||
var id = _a.id, config = _a.config, log = _a.log, userAgent = _a.userAgent, authToken = _a.authToken; | ||
var id = _a.id, config = _a.config, log = _a.log, userAgent = _a.userAgent, authTokenManager = _a.authTokenManager, _b = _a.newPool, newPool = _b === void 0 ? function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
return new (pool_1.default.bind.apply(pool_1.default, __spreadArray([void 0], __read(args), false)))(); | ||
} : _b; | ||
if (createChannelConnectionHook === void 0) { createChannelConnectionHook = null; } | ||
@@ -110,4 +152,4 @@ var _this = _super.call(this) || this; | ||
_this._log = log; | ||
_this._userAgent = userAgent; | ||
_this._authToken = authToken; | ||
_this._authTokenManager = authTokenManager; | ||
_this._authenticationProvider = new authentication_provider_1.default({ authTokenManager: authTokenManager, userAgent: userAgent }); | ||
_this._createChannelConnection = | ||
@@ -118,6 +160,7 @@ createChannelConnectionHook || | ||
}); | ||
_this._connectionPool = new pool_1.default({ | ||
_this._connectionPool = newPool({ | ||
create: _this._createConnection.bind(_this), | ||
destroy: _this._destroyConnection.bind(_this), | ||
validate: _this._validateConnection.bind(_this), | ||
validateOnAcquire: _this._validateConnectionOnAcquire.bind(_this), | ||
validateOnRelease: _this._validateConnectionOnRelease.bind(_this), | ||
installIdleObserver: PooledConnectionProvider._installIdleObserverOnConnection.bind(_this), | ||
@@ -128,2 +171,3 @@ removeIdleObserver: PooledConnectionProvider._removeIdleObserverOnConnection.bind(_this), | ||
}); | ||
_this._userAgent = userAgent; | ||
_this._openConnections = {}; | ||
@@ -140,4 +184,5 @@ return _this; | ||
*/ | ||
PooledConnectionProvider.prototype._createConnection = function (address, release) { | ||
PooledConnectionProvider.prototype._createConnection = function (_a, address, release) { | ||
var _this = this; | ||
var auth = _a.auth; | ||
return this._createChannelConnection(address).then(function (connection) { | ||
@@ -148,4 +193,3 @@ connection._release = function () { | ||
_this._openConnections[connection.id] = connection; | ||
return connection | ||
.connect(_this._userAgent, _this._authToken) | ||
return _this._authenticationProvider.authenticate({ connection: connection, auth: auth }) | ||
.catch(function (error) { | ||
@@ -159,2 +203,31 @@ // let's destroy this connection | ||
}; | ||
PooledConnectionProvider.prototype._validateConnectionOnAcquire = function (_a, conn) { | ||
var auth = _a.auth, skipReAuth = _a.skipReAuth; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var error_1; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
if (!this._validateConnection(conn)) { | ||
return [2 /*return*/, false]; | ||
} | ||
_b.label = 1; | ||
case 1: | ||
_b.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, this._authenticationProvider.authenticate({ connection: conn, auth: auth, skipReAuth: skipReAuth })]; | ||
case 2: | ||
_b.sent(); | ||
return [2 /*return*/, true]; | ||
case 3: | ||
error_1 = _b.sent(); | ||
this._log.debug("The connection ".concat(conn.id, " is not valid because of an error ").concat(error_1.code, " '").concat(error_1.message, "'")); | ||
return [2 /*return*/, false]; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
PooledConnectionProvider.prototype._validateConnectionOnRelease = function (conn) { | ||
return conn._sticky !== true && this._validateConnection(conn); | ||
}; | ||
/** | ||
@@ -171,3 +244,6 @@ * Check that a connection is usable | ||
var lifetime = Date.now() - conn.creationTimestamp; | ||
return lifetime <= maxConnectionLifetime; | ||
if (lifetime > maxConnectionLifetime) { | ||
return false; | ||
} | ||
return true; | ||
}; | ||
@@ -195,3 +271,3 @@ /** | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, this._connectionPool.acquire(address)]; | ||
case 0: return [4 /*yield*/, this._connectionPool.acquire({}, address)]; | ||
case 1: | ||
@@ -218,2 +294,73 @@ connection = _b.sent(); | ||
}; | ||
PooledConnectionProvider.prototype._verifyAuthentication = function (_a) { | ||
var getAddress = _a.getAddress, auth = _a.auth; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var connectionsToRelease, address, connection, lastMessageIsNotLogin, stickyConnection, error_2; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
connectionsToRelease = []; | ||
_b.label = 1; | ||
case 1: | ||
_b.trys.push([1, 8, 9, 11]); | ||
return [4 /*yield*/, getAddress()]; | ||
case 2: | ||
address = _b.sent(); | ||
return [4 /*yield*/, this._connectionPool.acquire({ auth: auth, skipReAuth: true }, address)]; | ||
case 3: | ||
connection = _b.sent(); | ||
connectionsToRelease.push(connection); | ||
lastMessageIsNotLogin = !connection.protocol().isLastMessageLogon(); | ||
if (!connection.supportsReAuth) { | ||
throw (0, neo4j_driver_core_1.newError)('Driver is connected to a database that does not support user switch.'); | ||
} | ||
if (!(lastMessageIsNotLogin && connection.supportsReAuth)) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, this._authenticationProvider.authenticate({ connection: connection, auth: auth, waitReAuth: true, forceReAuth: true })]; | ||
case 4: | ||
_b.sent(); | ||
return [3 /*break*/, 7]; | ||
case 5: | ||
if (!(lastMessageIsNotLogin && !connection.supportsReAuth)) return [3 /*break*/, 7]; | ||
return [4 /*yield*/, this._connectionPool.acquire({ auth: auth }, address, { requireNew: true })]; | ||
case 6: | ||
stickyConnection = _b.sent(); | ||
stickyConnection._sticky = true; | ||
connectionsToRelease.push(stickyConnection); | ||
_b.label = 7; | ||
case 7: return [2 /*return*/, true]; | ||
case 8: | ||
error_2 = _b.sent(); | ||
if (AUTHENTICATION_ERRORS.includes(error_2.code)) { | ||
return [2 /*return*/, false]; | ||
} | ||
throw error_2; | ||
case 9: return [4 /*yield*/, Promise.all(connectionsToRelease.map(function (conn) { return conn._release(); }))]; | ||
case 10: | ||
_b.sent(); | ||
return [7 /*endfinally*/]; | ||
case 11: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
PooledConnectionProvider.prototype._verifyStickyConnection = function (_a) { | ||
var auth = _a.auth, connection = _a.connection, address = _a.address; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var connectionWithSameCredentials, shouldCreateStickyConnection; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
connectionWithSameCredentials = lang_1.object.equals(auth, connection.authToken); | ||
shouldCreateStickyConnection = !connectionWithSameCredentials; | ||
connection._sticky = connectionWithSameCredentials && !connection.supportsReAuth; | ||
if (!(shouldCreateStickyConnection || connection._sticky)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, connection._release()]; | ||
case 1: | ||
_b.sent(); | ||
throw (0, neo4j_driver_core_1.newError)('Driver is connected to a database that does not support user switch.'); | ||
case 2: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
PooledConnectionProvider.prototype.close = function () { | ||
@@ -250,4 +397,17 @@ return __awaiter(this, void 0, void 0, function () { | ||
}; | ||
PooledConnectionProvider.prototype._handleAuthorizationExpired = function (error, address, connection) { | ||
this._authenticationProvider.handleError({ connection: connection, code: error.code }); | ||
if (error.code === 'Neo.ClientError.Security.AuthorizationExpired') { | ||
this._connectionPool.apply(address, function (conn) { conn.authToken = null; }); | ||
} | ||
if (connection) { | ||
connection.close().catch(function () { return undefined; }); | ||
} | ||
if (error.code === 'Neo.ClientError.Security.TokenExpired' && !(0, neo4j_driver_core_1.isStaticAuthTokenManger)(this._authTokenManager)) { | ||
error.retriable = true; | ||
} | ||
return error; | ||
}; | ||
return PooledConnectionProvider; | ||
}(neo4j_driver_core_1.ConnectionProvider)); | ||
exports.default = PooledConnectionProvider; |
@@ -144,3 +144,3 @@ "use strict"; | ||
var SERVICE_UNAVAILABLE = neo4j_driver_core_1.error.SERVICE_UNAVAILABLE, SESSION_EXPIRED = neo4j_driver_core_1.error.SESSION_EXPIRED; | ||
var Bookmarks = neo4j_driver_core_1.internal.bookmarks.Bookmarks, _a = neo4j_driver_core_1.internal.constants, READ = _a.ACCESS_MODE_READ, WRITE = _a.ACCESS_MODE_WRITE, BOLT_PROTOCOL_V3 = _a.BOLT_PROTOCOL_V3, BOLT_PROTOCOL_V4_0 = _a.BOLT_PROTOCOL_V4_0, BOLT_PROTOCOL_V4_4 = _a.BOLT_PROTOCOL_V4_4; | ||
var Bookmarks = neo4j_driver_core_1.internal.bookmarks.Bookmarks, _a = neo4j_driver_core_1.internal.constants, READ = _a.ACCESS_MODE_READ, WRITE = _a.ACCESS_MODE_WRITE, BOLT_PROTOCOL_V3 = _a.BOLT_PROTOCOL_V3, BOLT_PROTOCOL_V4_0 = _a.BOLT_PROTOCOL_V4_0, BOLT_PROTOCOL_V4_4 = _a.BOLT_PROTOCOL_V4_4, BOLT_PROTOCOL_V5_1 = _a.BOLT_PROTOCOL_V5_1; | ||
var PROCEDURE_NOT_FOUND_CODE = 'Neo.ClientError.Procedure.ProcedureNotFound'; | ||
@@ -154,2 +154,3 @@ var DATABASE_NOT_FOUND_CODE = 'Neo.ClientError.Database.DatabaseNotFound'; | ||
var STATEMENT_TYPE_ERROR = 'Neo.ClientError.Statement.TypeError'; | ||
var NOT_AVAILABLE = 'N/A'; | ||
var SYSTEM_DB_NAME = 'system'; | ||
@@ -161,4 +162,4 @@ var DEFAULT_DB_NAME = null; | ||
function RoutingConnectionProvider(_a) { | ||
var id = _a.id, address = _a.address, routingContext = _a.routingContext, hostNameResolver = _a.hostNameResolver, config = _a.config, log = _a.log, userAgent = _a.userAgent, authToken = _a.authToken, routingTablePurgeDelay = _a.routingTablePurgeDelay; | ||
var _this = _super.call(this, { id: id, config: config, log: log, userAgent: userAgent, authToken: authToken }, function (address) { | ||
var id = _a.id, address = _a.address, routingContext = _a.routingContext, hostNameResolver = _a.hostNameResolver, config = _a.config, log = _a.log, userAgent = _a.userAgent, authTokenManager = _a.authTokenManager, routingTablePurgeDelay = _a.routingTablePurgeDelay, newPool = _a.newPool; | ||
var _this = _super.call(this, { id: id, config: config, log: log, userAgent: userAgent, authTokenManager: authTokenManager, newPool: newPool }, function (address) { | ||
return (0, connection_1.createChannelConnection)(address, _this._config, _this._createConnectionErrorHandler(), _this._log, _this._routingContext); | ||
@@ -189,6 +190,5 @@ }) || this; | ||
}; | ||
RoutingConnectionProvider.prototype._handleAuthorizationExpired = function (error, address, database) { | ||
RoutingConnectionProvider.prototype._handleAuthorizationExpired = function (error, address, connection, database) { | ||
this._log.warn("Routing driver ".concat(this._id, " will close connections to ").concat(address, " for database '").concat(database, "' because of an error ").concat(error.code, " '").concat(error.message, "'")); | ||
this._connectionPool.purge(address).catch(function () { }); | ||
return error; | ||
return _super.prototype._handleAuthorizationExpired.call(this, error, address, connection, database); | ||
}; | ||
@@ -205,3 +205,3 @@ RoutingConnectionProvider.prototype._handleWriteFailure = function (error, address, database) { | ||
RoutingConnectionProvider.prototype.acquireConnection = function (_a) { | ||
var _b = _a === void 0 ? {} : _a, accessMode = _b.accessMode, database = _b.database, bookmarks = _b.bookmarks, impersonatedUser = _b.impersonatedUser, onDatabaseNameResolved = _b.onDatabaseNameResolved; | ||
var _b = _a === void 0 ? {} : _a, accessMode = _b.accessMode, database = _b.database, bookmarks = _b.bookmarks, impersonatedUser = _b.impersonatedUser, onDatabaseNameResolved = _b.onDatabaseNameResolved, auth = _b.auth; | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -214,4 +214,4 @@ var name, address, context, databaseSpecificErrorHandler, routingTable, connection, error_1, transformed; | ||
context = { database: database || DEFAULT_DB_NAME }; | ||
databaseSpecificErrorHandler = new connection_1.ConnectionErrorHandler(SESSION_EXPIRED, function (error, address) { return _this._handleUnavailability(error, address, context.database); }, function (error, address) { return _this._handleWriteFailure(error, address, context.database); }, function (error, address) { | ||
return _this._handleAuthorizationExpired(error, address, context.database); | ||
databaseSpecificErrorHandler = new connection_1.ConnectionErrorHandler(SESSION_EXPIRED, function (error, address) { return _this._handleUnavailability(error, address, context.database); }, function (error, address) { return _this._handleWriteFailure(error, address, context.database); }, function (error, address, conn) { | ||
return _this._handleAuthorizationExpired(error, address, conn, context.database); | ||
}); | ||
@@ -223,2 +223,3 @@ return [4 /*yield*/, this._freshRoutingTable({ | ||
impersonatedUser: impersonatedUser, | ||
auth: auth, | ||
onDatabaseNameResolved: function (databaseName) { | ||
@@ -253,12 +254,21 @@ context.database = context.database || databaseName; | ||
case 2: | ||
_c.trys.push([2, 4, , 5]); | ||
return [4 /*yield*/, this._acquireConnectionToServer(address, name, routingTable)]; | ||
_c.trys.push([2, 6, , 7]); | ||
return [4 /*yield*/, this._connectionPool.acquire({ auth: auth }, address)]; | ||
case 3: | ||
connection = _c.sent(); | ||
return [2 /*return*/, new connection_1.DelegateConnection(connection, databaseSpecificErrorHandler)]; | ||
if (!auth) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, this._verifyStickyConnection({ | ||
auth: auth, | ||
connection: connection, | ||
address: address | ||
})]; | ||
case 4: | ||
_c.sent(); | ||
return [2 /*return*/, connection]; | ||
case 5: return [2 /*return*/, new connection_1.DelegateConnection(connection, databaseSpecificErrorHandler)]; | ||
case 6: | ||
error_1 = _c.sent(); | ||
transformed = databaseSpecificErrorHandler.handleAndTransformError(error_1, address); | ||
throw transformed; | ||
case 5: return [2 /*return*/]; | ||
case 7: return [2 /*return*/]; | ||
} | ||
@@ -342,2 +352,12 @@ }); | ||
}; | ||
RoutingConnectionProvider.prototype.supportsSessionAuth = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this._hasProtocolVersion(function (version) { return version >= BOLT_PROTOCOL_V5_1; })]; | ||
case 1: return [2 /*return*/, _a.sent()]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RoutingConnectionProvider.prototype.getNegotiatedProtocolVersion = function () { | ||
@@ -350,2 +370,37 @@ var _this = this; | ||
}; | ||
RoutingConnectionProvider.prototype.verifyAuthentication = function (_a) { | ||
var database = _a.database, accessMode = _a.accessMode, auth = _a.auth; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_b) { | ||
return [2 /*return*/, this._verifyAuthentication({ | ||
auth: auth, | ||
getAddress: function () { return __awaiter(_this, void 0, void 0, function () { | ||
var context, routingTable, servers; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
context = { database: database || DEFAULT_DB_NAME }; | ||
return [4 /*yield*/, this._freshRoutingTable({ | ||
accessMode: accessMode, | ||
database: context.database, | ||
auth: auth, | ||
onDatabaseNameResolved: function (databaseName) { | ||
context.database = context.database || databaseName; | ||
} | ||
})]; | ||
case 1: | ||
routingTable = _a.sent(); | ||
servers = accessMode === WRITE ? routingTable.writers : routingTable.readers; | ||
if (servers.length === 0) { | ||
throw (0, neo4j_driver_core_1.newError)("No servers available for database '".concat(context.database, "' with access mode '").concat(accessMode, "'"), SERVICE_UNAVAILABLE); | ||
} | ||
return [2 /*return*/, servers[0]]; | ||
} | ||
}); | ||
}); } | ||
})]; | ||
}); | ||
}); | ||
}; | ||
RoutingConnectionProvider.prototype.verifyConnectivityAndGetServerInfo = function (_a) { | ||
@@ -422,7 +477,4 @@ var database = _a.database, accessMode = _a.accessMode; | ||
}; | ||
RoutingConnectionProvider.prototype._acquireConnectionToServer = function (address, serverName, routingTable) { | ||
return this._connectionPool.acquire(address); | ||
}; | ||
RoutingConnectionProvider.prototype._freshRoutingTable = function (_a) { | ||
var _b = _a === void 0 ? {} : _a, accessMode = _b.accessMode, database = _b.database, bookmarks = _b.bookmarks, impersonatedUser = _b.impersonatedUser, onDatabaseNameResolved = _b.onDatabaseNameResolved; | ||
var _b = _a === void 0 ? {} : _a, accessMode = _b.accessMode, database = _b.database, bookmarks = _b.bookmarks, impersonatedUser = _b.impersonatedUser, onDatabaseNameResolved = _b.onDatabaseNameResolved, auth = _b.auth; | ||
var currentRoutingTable = this._routingTableRegistry.get(database, function () { return new rediscovery_1.RoutingTable({ database: database }); }); | ||
@@ -433,12 +485,12 @@ if (!currentRoutingTable.isStaleFor(accessMode)) { | ||
this._log.info("Routing table is stale for database: \"".concat(database, "\" and access mode: \"").concat(accessMode, "\": ").concat(currentRoutingTable)); | ||
return this._refreshRoutingTable(currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved); | ||
return this._refreshRoutingTable(currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved, auth); | ||
}; | ||
RoutingConnectionProvider.prototype._refreshRoutingTable = function (currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved) { | ||
RoutingConnectionProvider.prototype._refreshRoutingTable = function (currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved, auth) { | ||
var knownRouters = currentRoutingTable.routers; | ||
if (this._useSeedRouter) { | ||
return this._fetchRoutingTableFromSeedRouterFallbackToKnownRouters(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved); | ||
return this._fetchRoutingTableFromSeedRouterFallbackToKnownRouters(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved, auth); | ||
} | ||
return this._fetchRoutingTableFromKnownRoutersFallbackToSeedRouter(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved); | ||
return this._fetchRoutingTableFromKnownRoutersFallbackToSeedRouter(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved, auth); | ||
}; | ||
RoutingConnectionProvider.prototype._fetchRoutingTableFromSeedRouterFallbackToKnownRouters = function (knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved) { | ||
RoutingConnectionProvider.prototype._fetchRoutingTableFromSeedRouterFallbackToKnownRouters = function (knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved, auth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -450,3 +502,3 @@ var seenRouters, _a, newRoutingTable, error, _b, newRoutingTable2, error2; | ||
seenRouters = []; | ||
return [4 /*yield*/, this._fetchRoutingTableUsingSeedRouter(seenRouters, this._seedRouter, currentRoutingTable, bookmarks, impersonatedUser)]; | ||
return [4 /*yield*/, this._fetchRoutingTableUsingSeedRouter(seenRouters, this._seedRouter, currentRoutingTable, bookmarks, impersonatedUser, auth)]; | ||
case 1: | ||
@@ -457,3 +509,3 @@ _a = __read.apply(void 0, [_c.sent(), 2]), newRoutingTable = _a[0], error = _a[1]; | ||
return [3 /*break*/, 4]; | ||
case 2: return [4 /*yield*/, this._fetchRoutingTableUsingKnownRouters(knownRouters, currentRoutingTable, bookmarks, impersonatedUser)]; | ||
case 2: return [4 /*yield*/, this._fetchRoutingTableUsingKnownRouters(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, auth)]; | ||
case 3: | ||
@@ -470,3 +522,3 @@ _b = __read.apply(void 0, [_c.sent(), 2]), newRoutingTable2 = _b[0], error2 = _b[1]; | ||
}; | ||
RoutingConnectionProvider.prototype._fetchRoutingTableFromKnownRoutersFallbackToSeedRouter = function (knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved) { | ||
RoutingConnectionProvider.prototype._fetchRoutingTableFromKnownRoutersFallbackToSeedRouter = function (knownRouters, currentRoutingTable, bookmarks, impersonatedUser, onDatabaseNameResolved, auth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -477,7 +529,7 @@ var _a, newRoutingTable, error; | ||
switch (_c.label) { | ||
case 0: return [4 /*yield*/, this._fetchRoutingTableUsingKnownRouters(knownRouters, currentRoutingTable, bookmarks, impersonatedUser)]; | ||
case 0: return [4 /*yield*/, this._fetchRoutingTableUsingKnownRouters(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, auth)]; | ||
case 1: | ||
_a = __read.apply(void 0, [_c.sent(), 2]), newRoutingTable = _a[0], error = _a[1]; | ||
if (!!newRoutingTable) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, this._fetchRoutingTableUsingSeedRouter(knownRouters, this._seedRouter, currentRoutingTable, bookmarks, impersonatedUser)]; | ||
return [4 /*yield*/, this._fetchRoutingTableUsingSeedRouter(knownRouters, this._seedRouter, currentRoutingTable, bookmarks, impersonatedUser, auth)]; | ||
case 2: | ||
@@ -493,3 +545,3 @@ // none of the known routers returned a valid routing table - try to use seed router address for rediscovery | ||
}; | ||
RoutingConnectionProvider.prototype._fetchRoutingTableUsingKnownRouters = function (knownRouters, currentRoutingTable, bookmarks, impersonatedUser) { | ||
RoutingConnectionProvider.prototype._fetchRoutingTableUsingKnownRouters = function (knownRouters, currentRoutingTable, bookmarks, impersonatedUser, auth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -499,3 +551,3 @@ var _a, newRoutingTable, error, lastRouterIndex; | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, this._fetchRoutingTable(knownRouters, currentRoutingTable, bookmarks, impersonatedUser)]; | ||
case 0: return [4 /*yield*/, this._fetchRoutingTable(knownRouters, currentRoutingTable, bookmarks, impersonatedUser, auth)]; | ||
case 1: | ||
@@ -514,3 +566,3 @@ _a = __read.apply(void 0, [_b.sent(), 2]), newRoutingTable = _a[0], error = _a[1]; | ||
}; | ||
RoutingConnectionProvider.prototype._fetchRoutingTableUsingSeedRouter = function (seenRouters, seedRouter, routingTable, bookmarks, impersonatedUser) { | ||
RoutingConnectionProvider.prototype._fetchRoutingTableUsingSeedRouter = function (seenRouters, seedRouter, routingTable, bookmarks, impersonatedUser, auth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -526,3 +578,3 @@ var resolvedAddresses, newAddresses; | ||
newAddresses = resolvedAddresses.filter(function (address) { return seenRouters.indexOf(address) < 0; }); | ||
return [4 /*yield*/, this._fetchRoutingTable(newAddresses, routingTable, bookmarks, impersonatedUser)]; | ||
return [4 /*yield*/, this._fetchRoutingTable(newAddresses, routingTable, bookmarks, impersonatedUser, auth)]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
@@ -550,3 +602,3 @@ } | ||
}; | ||
RoutingConnectionProvider.prototype._fetchRoutingTable = function (routerAddresses, routingTable, bookmarks, impersonatedUser) { | ||
RoutingConnectionProvider.prototype._fetchRoutingTable = function (routerAddresses, routingTable, bookmarks, impersonatedUser, auth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -570,3 +622,3 @@ var _this = this; | ||
} | ||
return [4 /*yield*/, this._createSessionForRediscovery(currentRouter, bookmarks, impersonatedUser)]; | ||
return [4 /*yield*/, this._createSessionForRediscovery(currentRouter, bookmarks, impersonatedUser, auth)]; | ||
case 2: | ||
@@ -598,5 +650,5 @@ _b = __read.apply(void 0, [_c.sent(), 2]), session = _b[0], error = _b[1]; | ||
}; | ||
RoutingConnectionProvider.prototype._createSessionForRediscovery = function (routerAddress, bookmarks, impersonatedUser) { | ||
RoutingConnectionProvider.prototype._createSessionForRediscovery = function (routerAddress, bookmarks, impersonatedUser, auth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var connection, databaseSpecificErrorHandler, connectionProvider, protocolVersion, error_4; | ||
var connection, databaseSpecificErrorHandler, delegateConnection, connectionProvider, protocolVersion, error_4; | ||
var _this = this; | ||
@@ -606,11 +658,24 @@ return __generator(this, function (_a) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4 /*yield*/, this._connectionPool.acquire(routerAddress)]; | ||
_a.trys.push([0, 4, , 5]); | ||
return [4 /*yield*/, this._connectionPool.acquire({ auth: auth }, routerAddress)]; | ||
case 1: | ||
connection = _a.sent(); | ||
if (!auth) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, this._verifyStickyConnection({ | ||
auth: auth, | ||
connection: connection, | ||
address: routerAddress | ||
})]; | ||
case 2: | ||
_a.sent(); | ||
_a.label = 3; | ||
case 3: | ||
databaseSpecificErrorHandler = connection_1.ConnectionErrorHandler.create({ | ||
errorCode: SESSION_EXPIRED, | ||
handleAuthorizationExpired: function (error, address) { return _this._handleAuthorizationExpired(error, address); } | ||
handleAuthorizationExpired: function (error, address, conn) { return _this._handleAuthorizationExpired(error, address, conn); } | ||
}); | ||
connectionProvider = new connection_provider_single_1.default(new connection_1.DelegateConnection(connection, databaseSpecificErrorHandler)); | ||
delegateConnection = !connection._sticky | ||
? new connection_1.DelegateConnection(connection, databaseSpecificErrorHandler) | ||
: new connection_1.DelegateConnection(connection); | ||
connectionProvider = new connection_provider_single_1.default(delegateConnection); | ||
protocolVersion = connection.protocol().version; | ||
@@ -631,6 +696,6 @@ if (protocolVersion < 4.0) { | ||
}), null]]; | ||
case 2: | ||
case 4: | ||
error_4 = _a.sent(); | ||
return [2 /*return*/, this._handleRediscoveryError(error_4, routerAddress)]; | ||
case 3: return [2 /*return*/]; | ||
case 5: return [2 /*return*/]; | ||
} | ||
@@ -821,3 +886,4 @@ }); | ||
INVALID_REQUEST_ERROR, | ||
STATEMENT_TYPE_ERROR | ||
STATEMENT_TYPE_ERROR, | ||
NOT_AVAILABLE | ||
].includes(error.code); | ||
@@ -824,0 +890,0 @@ } |
@@ -152,2 +152,3 @@ "use strict"; | ||
var _this = _super.call(this, errorHandler) || this; | ||
_this._authToken = null; | ||
_this._reseting = false; | ||
@@ -180,2 +181,19 @@ _this._resetObservers = []; | ||
} | ||
Object.defineProperty(ChannelConnection.prototype, "authToken", { | ||
get: function () { | ||
return this._authToken; | ||
}, | ||
set: function (value) { | ||
this._authToken = value; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(ChannelConnection.prototype, "supportsReAuth", { | ||
get: function () { | ||
return this._protocol.supportsReAuth; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(ChannelConnection.prototype, "id", { | ||
@@ -204,4 +222,36 @@ get: function () { | ||
*/ | ||
ChannelConnection.prototype.connect = function (userAgent, authToken) { | ||
return this._initialize(userAgent, authToken); | ||
ChannelConnection.prototype.connect = function (userAgent, authToken, waitReAuth) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (this._protocol.initialized && !this._protocol.supportsReAuth) { | ||
throw (0, neo4j_driver_core_1.newError)('Connection does not support re-auth'); | ||
} | ||
this._authToken = authToken; | ||
if (!!this._protocol.initialized) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, this._initialize(userAgent, authToken)]; | ||
case 1: return [2 /*return*/, _a.sent()]; | ||
case 2: | ||
if (!waitReAuth) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, new Promise(function (resolve, reject) { | ||
_this._protocol.logoff({ | ||
onError: reject | ||
}); | ||
_this._protocol.logon({ | ||
authToken: authToken, | ||
onError: reject, | ||
onComplete: function () { return resolve(_this); }, | ||
flush: true | ||
}); | ||
})]; | ||
case 3: return [2 /*return*/, _a.sent()]; | ||
case 4: | ||
this._protocol.logoff(); | ||
this._protocol.logon({ authToken: authToken, flush: true }); | ||
return [2 /*return*/, this]; | ||
} | ||
}); | ||
}); | ||
}; | ||
@@ -208,0 +258,0 @@ /** |
@@ -79,2 +79,19 @@ "use strict"; | ||
}); | ||
Object.defineProperty(DelegateConnection.prototype, "authToken", { | ||
get: function () { | ||
return this._delegate.authToken; | ||
}, | ||
set: function (value) { | ||
this._delegate.authToken = value; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(DelegateConnection.prototype, "supportsReAuth", { | ||
get: function () { | ||
return this._delegate.supportsReAuth; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(DelegateConnection.prototype, "address", { | ||
@@ -103,4 +120,4 @@ get: function () { | ||
}; | ||
DelegateConnection.prototype.connect = function (userAgent, authToken) { | ||
return this._delegate.connect(userAgent, authToken); | ||
DelegateConnection.prototype.connect = function (userAgent, authToken, waitReAuth) { | ||
return this._delegate.connect(userAgent, authToken, waitReAuth); | ||
}; | ||
@@ -107,0 +124,0 @@ DelegateConnection.prototype.write = function (message, observer, flush) { |
@@ -47,11 +47,11 @@ "use strict"; | ||
*/ | ||
ConnectionErrorHandler.prototype.handleAndTransformError = function (error, address) { | ||
ConnectionErrorHandler.prototype.handleAndTransformError = function (error, address, connection) { | ||
if (isAutorizationExpiredError(error)) { | ||
return this._handleAuthorizationExpired(error, address); | ||
return this._handleAuthorizationExpired(error, address, connection); | ||
} | ||
if (isAvailabilityError(error)) { | ||
return this._handleUnavailability(error, address); | ||
return this._handleUnavailability(error, address, connection); | ||
} | ||
if (isFailureToWrite(error)) { | ||
return this._handleWriteFailure(error, address); | ||
return this._handleWriteFailure(error, address, connection); | ||
} | ||
@@ -58,0 +58,0 @@ return error; |
@@ -47,2 +47,19 @@ "use strict"; | ||
}); | ||
Object.defineProperty(Connection.prototype, "authToken", { | ||
get: function () { | ||
throw new Error('not implemented'); | ||
}, | ||
set: function (value) { | ||
throw new Error('not implemented'); | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Connection.prototype, "supportsReAuth", { | ||
get: function () { | ||
throw new Error('not implemented'); | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
/** | ||
@@ -134,3 +151,3 @@ * @returns {boolean} whether this connection is in a working condition | ||
if (this._errorHandler) { | ||
return this._errorHandler.handleAndTransformError(error, address); | ||
return this._errorHandler.handleAndTransformError(error, address, this); | ||
} | ||
@@ -137,0 +154,0 @@ return error; |
@@ -44,3 +44,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.functional = void 0; | ||
exports.object = exports.functional = void 0; | ||
exports.functional = __importStar(require("./functional")); | ||
exports.object = __importStar(require("./object")); |
@@ -65,11 +65,14 @@ "use strict"; | ||
/** | ||
* @param {function(address: ServerAddress, function(address: ServerAddress, resource: object): Promise<object>): Promise<object>} create | ||
* @param {function(acquisitionContext: object, address: ServerAddress, function(address: ServerAddress, resource: object): Promise<object>): Promise<object>} create | ||
* an allocation function that creates a promise with a new resource. It's given an address for which to | ||
* allocate the connection and a function that will return the resource to the pool if invoked, which is | ||
* meant to be called on .dispose or .close or whatever mechanism the resource uses to finalize. | ||
* @param {function(acquisitionContext: object, resource: object): boolean} validateOnAcquire | ||
* called at various times when an instance is acquired | ||
* If this returns false, the resource will be evicted | ||
* @param {function(resource: object): boolean} validateOnRelease | ||
* called at various times when an instance is released | ||
* If this returns false, the resource will be evicted | ||
* @param {function(resource: object): Promise<void>} destroy | ||
* called with the resource when it is evicted from this pool | ||
* @param {function(resource: object): boolean} validate | ||
* called at various times (like when an instance is acquired and when it is returned. | ||
* If this returns false, the resource will be evicted | ||
* @param {function(resource: object, observer: { onError }): void} installIdleObserver | ||
@@ -83,6 +86,7 @@ * called when the resource is released back to pool | ||
function Pool(_a) { | ||
var _b = _a === void 0 ? {} : _a, _c = _b.create, create = _c === void 0 ? function (address, release) { return Promise.resolve(); } : _c, _d = _b.destroy, destroy = _d === void 0 ? function (conn) { return Promise.resolve(); } : _d, _e = _b.validate, validate = _e === void 0 ? function (conn) { return true; } : _e, _f = _b.installIdleObserver, installIdleObserver = _f === void 0 ? function (conn, observer) { } : _f, _g = _b.removeIdleObserver, removeIdleObserver = _g === void 0 ? function (conn) { } : _g, _h = _b.config, config = _h === void 0 ? pool_config_1.default.defaultConfig() : _h, _j = _b.log, log = _j === void 0 ? Logger.noOp() : _j; | ||
var _b = _a === void 0 ? {} : _a, _c = _b.create, create = _c === void 0 ? function (acquisitionContext, address, release) { return Promise.resolve(); } : _c, _d = _b.destroy, destroy = _d === void 0 ? function (conn) { return Promise.resolve(); } : _d, _e = _b.validateOnAcquire, validateOnAcquire = _e === void 0 ? function (acquisitionContext, conn) { return true; } : _e, _f = _b.validateOnRelease, validateOnRelease = _f === void 0 ? function (conn) { return true; } : _f, _g = _b.installIdleObserver, installIdleObserver = _g === void 0 ? function (conn, observer) { } : _g, _h = _b.removeIdleObserver, removeIdleObserver = _h === void 0 ? function (conn) { } : _h, _j = _b.config, config = _j === void 0 ? pool_config_1.default.defaultConfig() : _j, _k = _b.log, log = _k === void 0 ? Logger.noOp() : _k; | ||
this._create = create; | ||
this._destroy = destroy; | ||
this._validate = validate; | ||
this._validateOnAcquire = validateOnAcquire; | ||
this._validateOnRelease = validateOnRelease; | ||
this._installIdleObserver = installIdleObserver; | ||
@@ -102,6 +106,9 @@ this._removeIdleObserver = removeIdleObserver; | ||
* Acquire and idle resource fom the pool or create a new one. | ||
* @param {object} acquisitionContext the acquisition context used for create and validateOnAcquire connection | ||
* @param {ServerAddress} address the address for which we're acquiring. | ||
* @param {object} config the config | ||
* @param {boolean} config.requireNew Indicate it requires a new resource | ||
* @return {Promise<Object>} resource that is ready to use. | ||
*/ | ||
Pool.prototype.acquire = function (address) { | ||
Pool.prototype.acquire = function (acquisitionContext, address, config) { | ||
var _this = this; | ||
@@ -135,3 +142,3 @@ var key = address.asKey(); | ||
}, _this._acquisitionTimeout); | ||
request = new PendingRequest(key, resolve, reject, timeoutId, _this._log); | ||
request = new PendingRequest(key, acquisitionContext, config, resolve, reject, timeoutId, _this._log); | ||
allRequests[key].push(request); | ||
@@ -149,2 +156,8 @@ _this._processPendingAcquireRequests(address); | ||
}; | ||
Pool.prototype.apply = function (address, resourceConsumer) { | ||
var key = address.asKey(); | ||
if (key in this._pools) { | ||
this._pools[key].apply(resourceConsumer); | ||
} | ||
}; | ||
/** | ||
@@ -215,5 +228,5 @@ * Destroy all idle resources in this pool. | ||
}; | ||
Pool.prototype._acquire = function (address) { | ||
Pool.prototype._acquire = function (acquisitionContext, address, requireNew) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var key, pool, resource_1, numConnections, resource; | ||
var key, pool, resource_1, numConnections, resource, numConnections, resource_2; | ||
var _this = this; | ||
@@ -228,10 +241,13 @@ return __generator(this, function (_a) { | ||
pool = this._getOrInitializePoolFor(key); | ||
if (!!requireNew) return [3 /*break*/, 6]; | ||
_a.label = 1; | ||
case 1: | ||
if (!pool.length) return [3 /*break*/, 5]; | ||
if (!pool.length) return [3 /*break*/, 6]; | ||
resource_1 = pool.pop(); | ||
if (!this._validate(resource_1)) return [3 /*break*/, 2]; | ||
if (this._removeIdleObserver) { | ||
this._removeIdleObserver(resource_1); | ||
} | ||
return [4 /*yield*/, this._validateOnAcquire(acquisitionContext, resource_1)]; | ||
case 2: | ||
if (!_a.sent()) return [3 /*break*/, 3]; | ||
// idle resource is valid and can be acquired | ||
@@ -243,8 +259,10 @@ resourceAcquired(key, this._activeResourceCounts); | ||
return [2 /*return*/, { resource: resource_1, pool: pool }]; | ||
case 2: return [4 /*yield*/, this._destroy(resource_1)]; | ||
case 3: | ||
pool.removeInUse(resource_1); | ||
return [4 /*yield*/, this._destroy(resource_1)]; | ||
case 4: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: return [3 /*break*/, 1]; | ||
case 5: | ||
_a.label = 5; | ||
case 5: return [3 /*break*/, 1]; | ||
case 6: | ||
// Ensure requested max pool size | ||
@@ -261,9 +279,21 @@ if (this._maxSize > 0) { | ||
this._pendingCreates[key] = this._pendingCreates[key] + 1; | ||
_a.label = 6; | ||
case 6: | ||
_a.trys.push([6, , 8, 9]); | ||
return [4 /*yield*/, this._create(address, function (address, resource) { return _this._release(address, resource, pool); })]; | ||
_a.label = 7; | ||
case 7: | ||
_a.trys.push([7, , 11, 12]); | ||
numConnections = this.activeResourceCount(address) + pool.length; | ||
if (!(numConnections >= this._maxSize && requireNew)) return [3 /*break*/, 9]; | ||
resource_2 = pool.pop(); | ||
if (this._removeIdleObserver) { | ||
this._removeIdleObserver(resource_2); | ||
} | ||
pool.removeInUse(resource_2); | ||
return [4 /*yield*/, this._destroy(resource_2)]; | ||
case 8: | ||
_a.sent(); | ||
_a.label = 9; | ||
case 9: return [4 /*yield*/, this._create(acquisitionContext, address, function (address, resource) { return _this._release(address, resource, pool); })]; | ||
case 10: | ||
// Invoke callback that creates actual connection | ||
resource = _a.sent(); | ||
pool.pushInUse(resource); | ||
resourceAcquired(key, this._activeResourceCounts); | ||
@@ -273,7 +303,7 @@ if (this._log.isDebugEnabled()) { | ||
} | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
return [3 /*break*/, 12]; | ||
case 11: | ||
this._pendingCreates[key] = this._pendingCreates[key] - 1; | ||
return [7 /*endfinally*/]; | ||
case 9: return [2 /*return*/, { resource: resource, pool: pool }]; | ||
case 12: return [2 /*return*/, { resource: resource, pool: pool }]; | ||
} | ||
@@ -291,12 +321,15 @@ }); | ||
key = address.asKey(); | ||
if (!pool.isActive()) return [3 /*break*/, 4]; | ||
if (!!this._validate(resource)) return [3 /*break*/, 2]; | ||
if (!pool.isActive()) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, this._validateOnRelease(resource)]; | ||
case 1: | ||
if (!!(_a.sent())) return [3 /*break*/, 3]; | ||
if (this._log.isDebugEnabled()) { | ||
this._log.debug("".concat(resource, " destroyed and can't be released to the pool ").concat(key, " because it is not functional")); | ||
} | ||
pool.removeInUse(resource); | ||
return [4 /*yield*/, this._destroy(resource)]; | ||
case 1: | ||
case 2: | ||
_a.sent(); | ||
return [3 /*break*/, 3]; | ||
case 2: | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
if (this._installIdleObserver) { | ||
@@ -309,2 +342,3 @@ this._installIdleObserver(resource, { | ||
_this._pools[key] = pool.filter(function (r) { return r !== resource; }); | ||
pool.removeInUse(resource); | ||
} | ||
@@ -322,5 +356,5 @@ // let's not care about background clean-ups due to errors but just trigger the destroy | ||
} | ||
_a.label = 3; | ||
case 3: return [3 /*break*/, 6]; | ||
case 4: | ||
_a.label = 4; | ||
case 4: return [3 /*break*/, 7]; | ||
case 5: | ||
// key has been purged, don't put it back, just destroy the resource | ||
@@ -330,7 +364,8 @@ if (this._log.isDebugEnabled()) { | ||
} | ||
pool.removeInUse(resource); | ||
return [4 /*yield*/, this._destroy(resource)]; | ||
case 5: | ||
case 6: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: | ||
_a.label = 7; | ||
case 7: | ||
resourceReleased(key, this._activeResourceCounts); | ||
@@ -377,3 +412,3 @@ this._processPendingAcquireRequests(address); | ||
if (pendingRequest_1) { | ||
this._acquire(address) | ||
this._acquire(pendingRequest_1.context, address, pendingRequest_1.requireNew) | ||
.catch(function (error) { | ||
@@ -443,4 +478,5 @@ // failed to acquire/create a new connection to resolve the pending acquire request | ||
var PendingRequest = /** @class */ (function () { | ||
function PendingRequest(key, resolve, reject, timeoutId, log) { | ||
function PendingRequest(key, context, config, resolve, reject, timeoutId, log) { | ||
this._key = key; | ||
this._context = context; | ||
this._resolve = resolve; | ||
@@ -451,3 +487,18 @@ this._reject = reject; | ||
this._completed = false; | ||
this._config = config || {}; | ||
} | ||
Object.defineProperty(PendingRequest.prototype, "context", { | ||
get: function () { | ||
return this._context; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(PendingRequest.prototype, "requireNew", { | ||
get: function () { | ||
return this._config.requireNew || false; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
PendingRequest.prototype.isCompleted = function () { | ||
@@ -481,2 +532,3 @@ return this._completed; | ||
this._elements = []; | ||
this._elementsInUse = new Set(); | ||
} | ||
@@ -488,2 +540,4 @@ SingleAddressPool.prototype.isActive = function () { | ||
this._active = false; | ||
this._elements = []; | ||
this._elementsInUse = new Set(); | ||
}; | ||
@@ -494,2 +548,6 @@ SingleAddressPool.prototype.filter = function (predicate) { | ||
}; | ||
SingleAddressPool.prototype.apply = function (resourceConsumer) { | ||
this._elements.forEach(resourceConsumer); | ||
this._elementsInUse.forEach(resourceConsumer); | ||
}; | ||
Object.defineProperty(SingleAddressPool.prototype, "length", { | ||
@@ -503,9 +561,18 @@ get: function () { | ||
SingleAddressPool.prototype.pop = function () { | ||
return this._elements.pop(); | ||
var element = this._elements.pop(); | ||
this._elementsInUse.add(element); | ||
return element; | ||
}; | ||
SingleAddressPool.prototype.push = function (element) { | ||
this._elementsInUse.delete(element); | ||
return this._elements.push(element); | ||
}; | ||
SingleAddressPool.prototype.pushInUse = function (element) { | ||
this._elementsInUse.add(element); | ||
}; | ||
SingleAddressPool.prototype.removeInUse = function (element) { | ||
this._elementsInUse.delete(element); | ||
}; | ||
return SingleAddressPool; | ||
}()); | ||
exports.default = Pool; |
{ | ||
"name": "neo4j-driver-bolt-connection", | ||
"version": "5.7.0", | ||
"version": "5.8.0", | ||
"description": "Implements the connection with the Neo4j Database using the Bolt Protocol", | ||
@@ -43,6 +43,6 @@ "main": "lib/index.js", | ||
"buffer": "^6.0.3", | ||
"neo4j-driver-core": "^5.7.0", | ||
"neo4j-driver-core": "^5.8.0", | ||
"string_decoder": "^1.3.0" | ||
}, | ||
"gitHead": "dd93e78d7b189c59765fe6bc0104c5d4a5fbd15d" | ||
"gitHead": "d8c4e0f4f9643f99da56bb8f1d179d0ec4b3b3ab" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
577066
86
12441
Updatedneo4j-driver-core@^5.8.0