UNPKG

kysely

Version:
126 lines (125 loc) 4.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RuntimeDriver = void 0; const performance_now_js_1 = require("../util/performance-now.js"); /** * A small wrapper around {@link Driver} that makes sure the driver is * initialized before it is used, only initialized and destroyed * once etc. */ class RuntimeDriver { #driver; #log; #initPromise; #initDone; #destroyPromise; #connections = new WeakSet(); constructor(driver, log) { this.#initDone = false; this.#driver = driver; this.#log = log; } async init() { if (this.#destroyPromise) { throw new Error('driver has already been destroyed'); } if (!this.#initPromise) { this.#initPromise = this.#driver .init() .then(() => { this.#initDone = true; }) .catch((err) => { this.#initPromise = undefined; return Promise.reject(err); }); } await this.#initPromise; } async acquireConnection() { if (this.#destroyPromise) { throw new Error('driver has already been destroyed'); } if (!this.#initDone) { await this.init(); } const connection = await this.#driver.acquireConnection(); if (!this.#connections.has(connection)) { if (this.#needsLogging()) { this.#addLogging(connection); } this.#connections.add(connection); } return connection; } async releaseConnection(connection) { await this.#driver.releaseConnection(connection); } beginTransaction(connection, settings) { return this.#driver.beginTransaction(connection, settings); } commitTransaction(connection) { return this.#driver.commitTransaction(connection); } rollbackTransaction(connection) { return this.#driver.rollbackTransaction(connection); } async destroy() { if (!this.#initPromise) { return; } await this.#initPromise; if (!this.#destroyPromise) { this.#destroyPromise = this.#driver.destroy().catch((err) => { this.#destroyPromise = undefined; return Promise.reject(err); }); } await this.#destroyPromise; } #needsLogging() { return (this.#log.isLevelEnabled('query') || this.#log.isLevelEnabled('error')); } // This method monkey patches the database connection's executeQuery method // by adding logging code around it. Monkey patching is not pretty, but it's // the best option in this case. #addLogging(connection) { const executeQuery = connection.executeQuery; connection.executeQuery = async (compiledQuery) => { let caughtError; const startTime = (0, performance_now_js_1.performanceNow)(); try { return await executeQuery.call(connection, compiledQuery); } catch (error) { caughtError = error; await this.#logError(error, compiledQuery, startTime); throw error; } finally { if (!caughtError) { await this.#logQuery(compiledQuery, startTime); } } }; } async #logError(error, compiledQuery, startTime) { await this.#log.error(() => ({ level: 'error', error, query: compiledQuery, queryDurationMillis: this.#calculateDurationMillis(startTime), })); } async #logQuery(compiledQuery, startTime) { await this.#log.query(() => ({ level: 'query', query: compiledQuery, queryDurationMillis: this.#calculateDurationMillis(startTime), })); } #calculateDurationMillis(startTime) { return (0, performance_now_js_1.performanceNow)() - startTime; } } exports.RuntimeDriver = RuntimeDriver;