@opra/sqb
Version:
Opra SQB adapter package
85 lines (84 loc) • 2.66 kB
JavaScript
import { ServiceBase } from '@opra/core';
import { SqbConnection } from '@sqb/connect';
const transactionKey = Symbol.for('transaction');
/**
* @class SqbServiceBase
* @template T - The data type class type of the resource
*/
export class SqbServiceBase extends ServiceBase {
/**
* Constructs a new instance
*
* @param [options] - The options for the service.
* @constructor
*/
constructor(options) {
super();
this.db = options?.db;
}
/**
* Executes the provided function within a transaction.
*
* @param callback - The function to be executed within the transaction.
*/
async withTransaction(callback) {
const ctx = this.context;
let closeSessionOnFinish = false;
let connection = ctx[transactionKey];
if (!connection) {
/** Determine the SqbClient or SqbConnection instance */
const db = await this.getConnection();
if (db instanceof SqbConnection) {
connection = db;
}
else {
/** Acquire a connection. New connection should be at the end */
connection = await db.acquire({ autoCommit: false });
closeSessionOnFinish = true;
}
/** Store transaction connection in current context */
ctx[transactionKey] = connection;
}
const oldInTransaction = connection.inTransaction;
connection.retain();
try {
if (!oldInTransaction)
await connection.startTransaction();
const out = await callback(connection, this);
if (!oldInTransaction && connection.inTransaction)
await connection.commit();
return out;
}
catch (e) {
if (!oldInTransaction && connection.inTransaction)
await connection.rollback();
throw e;
}
finally {
delete ctx[transactionKey];
/** Release connection */
if (closeSessionOnFinish) {
await connection.close();
}
else
connection.release();
}
}
/**
* Retrieves the database connection.
*
* @protected
*
* @throws {Error} If the context or database is not set.
*/
getConnection() {
const ctx = this.context;
let db = ctx[transactionKey];
if (db)
return db;
db = typeof this.db === 'function' ? this.db(this) : this.db;
if (db)
return db;
throw new Error(`Database not set!`);
}
}