UNPKG

@breautek/storm

Version:

Object-Oriented REST API framework

174 lines (171 loc) 5.61 kB
"use strict"; /* Copyright 2017-2021 Norman Breau 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. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.DatabaseConnection = exports.RECURRING_WARNING_TIMER = exports.DEFAULT_QUERY_TIMEOUT = exports.LINGER_WARNING = void 0; const instance_1 = require("./instance"); exports.LINGER_WARNING = 60000; exports.DEFAULT_QUERY_TIMEOUT = 3600000; exports.RECURRING_WARNING_TIMER = 60000; const TAG = 'DatabaseConnection'; /** * Do not call `new Database` directly. Use `Database.getConnection` to create a `DatabaseConnection` object. * @abstract * @implements `IDatabaseConnection` * @class */ class DatabaseConnection { constructor(api, isReadOnly, instantiationStack) { this.$api = api; this.$readOnly = isReadOnly; this.$instantiationStack = (instantiationStack || '').replace(/Error:/, 'Warning:'); this.$open = true; let config = (0, instance_1.getInstance)().getConfig(); this.$timeout = config.database ? config.database.query_timeout : null; if (isNaN(this.$timeout)) { this.$timeout = exports.DEFAULT_QUERY_TIMEOUT; } this.$lingerTickCount = 0; this.$armLingerWarning(); } $triggerLingerWarning() { let elapsed = (exports.LINGER_WARNING + (exports.RECURRING_WARNING_TIMER * this.$lingerTickCount)) / 1000; (0, instance_1.getInstance)().getLogger().warn(TAG, `Database connection has lingered for ${elapsed}s of inactivity.\n\n${this.$instantiationStack}`); } setInstantiationStack(stack) { this.$instantiationStack = stack; } /** * Gets the callback stacktrace to determine what opened * this connection. Useful for debugging lingering connections. * @returns string - A stacktrace */ getInstantiationStack() { return this.$instantiationStack; } $disarmLingerWarnings() { clearTimeout(this.$lingerTimer); clearInterval(this.$lingerInterval); this.$lingerTickCount = 0; } $armLingerWarning() { this.$disarmLingerWarnings(); this.$lingerTimer = setTimeout(() => { this.$triggerLingerWarning(); this.$lingerInterval = setInterval(() => { this.$lingerTickCount++; this.$triggerLingerWarning(); }, exports.RECURRING_WARNING_TIMER); }, exports.LINGER_WARNING); } /** * Gets the underlying Database API * @returns any */ getAPI() { return this.$api; } /** * Returns true if connection was created without * write access * @returns boolean */ isReadOnly() { return this.$readOnly; } /** * Sets the timeout of this connectino * * @param timeout in milliseconds */ setTimeout(timeout) { if (isNaN(timeout)) { throw new TypeError('setTimeout expects a number in parameter 1.'); } this.$timeout = timeout; } /** * Returns the current timeout setting * @returns number in milliseconds */ getTimeout() { return this.$timeout; } /** * Queries the database for a dataset. * * @param {Query} query The database query * @async * @returns Promise<TQueryResult> */ async query(query) { this.$armLingerWarning(); let queryStr = null; queryStr = query.getQuery(this); let params = query.getParametersForQuery(); await query.onPreQuery(this); let out = null; let e = null; try { let results = await this._query(queryStr, params); out = await query.onPostProcess(this, results); } catch (ex) { e = ex; } await query.onPostQuery(this); if (e !== null) { throw e; } return out; } /** * * @param query The database query * @param params Parameters for the query * @param streamOptions Stream options * @returns Readable */ stream(query, streamOptions) { this.$armLingerWarning(); let queryStr = null; let params = query.getParametersForQuery(); queryStr = query.getQuery(this); return this._stream(queryStr, params, streamOptions); } /** * Closes the connection. May error if connection has an active transaction. * if `forceClose` boolean is true, it will force close the connection, regardless * of transaction state. * * @param forceClose optional boolean * @async * @returns Promise<void> */ async close(forceClose = false) { if (this.isClosed()) { return; } await this._close(forceClose); this.$open = false; this.$disarmLingerWarnings(); } /** * Returns true if the connection has been closed. */ isClosed() { return !this.$open; } } exports.DatabaseConnection = DatabaseConnection; //# sourceMappingURL=DatabaseConnection.js.map