UNPKG

@n8n/typeorm

Version:

Data-Mapper ORM for TypeScript, ES7, ES6, ES5. Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, MongoDB databases.

128 lines (126 loc) 4.52 kB
import { captureException } from "@sentry/node"; import { Mutex, withTimeout, E_TIMEOUT } from "async-mutex"; import assert from "assert"; import { DriverAlreadyReleasedError } from "../../error/DriverAlreadyReleasedError"; import { LeasedDbConnection } from "./LeasedDbConnection"; import { TimeoutTimer } from "./Timer"; /** * A single write connection to the database. */ export class SqliteWriteConnection { constructor(sqliteLibray, options) { this.sqliteLibray = sqliteLibray; this.options = options; this.writeConnectionPromise = null; /** * Should the connection be re-created after it has been released */ this.isConnectionValid = true; this.isReleased = false; const acquireTimeout = options.acquireTimeout; this.writeConnectionMutex = withTimeout(new Mutex(), acquireTimeout); } async connect() { this.assertNotReleased(); await this.writeConnectionMutex.runExclusive(async () => await this.createConnection()); } async close() { if (this.isReleased) return; this.isReleased = true; // Cancel any pending acquires this.writeConnectionMutex.cancel(); // If there is an existing lease, request it to be released if (this.dbLease) { this.dbLease.requestRelease(); } const timeoutTimer = TimeoutTimer.start(this.options.destroyTimeout); await Promise.race([ this.writeConnectionMutex.acquire(), timeoutTimer.promise, ]).finally(() => { timeoutTimer.clear(); }); if (this.writeConnectionPromise) { const dbConnection = await this.writeConnectionPromise; this.sqliteLibray.destroyDatabaseConnection(dbConnection); } } async runExclusive(dbLeaseHolder, callback) { this.assertNotReleased(); try { return await this.writeConnectionMutex.runExclusive(async () => { this.dbLease = await this.createAndGetConnection(dbLeaseHolder); const result = await callback(this.dbLease); return result; }); } catch (error) { if (error === E_TIMEOUT) { captureException(error); } throw error; } finally { this.dbLease = undefined; } } async leaseConnection(dbLeaseHolder) { this.assertNotReleased(); try { await this.writeConnectionMutex.acquire(); } catch (error) { captureException(error); throw error; } this.dbLease = await this.createAndGetConnection(dbLeaseHolder); return this.dbLease; } invalidateConnection(leasedDbConnection) { assert(this.dbLease === leasedDbConnection); assert(this.writeConnectionMutex.isLocked()); assert(this.writeConnectionPromise); this.isConnectionValid = false; } async releaseConnection(leasedDbConnection) { assert(this.dbLease === leasedDbConnection); assert(this.writeConnectionMutex.isLocked()); assert(this.writeConnectionPromise); try { const connection = await this.writeConnectionPromise; if (!this.isConnectionValid) { this.sqliteLibray.destroyDatabaseConnection(connection); this.writeConnectionPromise = null; } } finally { this.dbLease = undefined; this.writeConnectionMutex.release(); } } async createAndGetConnection(dbLeaseHolder) { if (!this.writeConnectionPromise) { this.writeConnectionPromise = this.sqliteLibray.createDatabaseConnection(); } const dbConnection = await this.writeConnectionPromise; assert(!this.dbLease); return new LeasedDbConnection(dbConnection, this, dbLeaseHolder); } async createConnection() { this.assertNotReleased(); if (this.writeConnectionPromise) { throw new Error("Connection already created"); } this.writeConnectionPromise = this.sqliteLibray.createDatabaseConnection(); return this.writeConnectionPromise; } assertNotReleased() { if (this.isReleased) { throw new DriverAlreadyReleasedError(); } } } //# sourceMappingURL=SqliteWriteConnection.js.map