release: WRNexusJS 0.8.0
This commit is contained in:
@@ -50,12 +50,32 @@ export interface Db {
|
||||
close(): void | Promise<void>;
|
||||
}
|
||||
|
||||
interface DbLifecycle {
|
||||
closing: boolean;
|
||||
active: Set<Promise<unknown>>;
|
||||
closePromise?: Promise<void>;
|
||||
}
|
||||
|
||||
/** Build a `Db` over a query runner (the driver at top level, or a transaction). */
|
||||
function dbOver(runner: TxHandle, driver: Driver): Db {
|
||||
function dbOver(
|
||||
runner: TxHandle,
|
||||
driver: Driver,
|
||||
lifecycle: DbLifecycle,
|
||||
transactionScope = false,
|
||||
): Db {
|
||||
function run<T>(operation: () => Promise<T>): Promise<T> {
|
||||
if (lifecycle.closing && !transactionScope) {
|
||||
return Promise.reject(new Error("WRN-DB-CLOSED: database is closing or closed"));
|
||||
}
|
||||
const promise = Promise.resolve().then(operation);
|
||||
lifecycle.active.add(promise);
|
||||
void promise.finally(() => lifecycle.active.delete(promise)).catch(() => {});
|
||||
return promise;
|
||||
}
|
||||
const db: Db = {
|
||||
driver,
|
||||
async all(sql, params = [], model) {
|
||||
const rows = await runner.query(sql, params);
|
||||
const rows = await run(() => runner.query(sql, params));
|
||||
return (model ? rows.map((r) => model.parse(r)) : rows) as never;
|
||||
},
|
||||
async one(sql, params = [], model) {
|
||||
@@ -63,18 +83,25 @@ function dbOver(runner: TxHandle, driver: Driver): Db {
|
||||
return (rows[0] ?? null) as never;
|
||||
},
|
||||
exec(sql, params = []) {
|
||||
return runner.exec(sql, params);
|
||||
return run(() => runner.exec(sql, params));
|
||||
},
|
||||
async tx(fn) {
|
||||
// Top level opens a real transaction; inside one, reuse the current tx.
|
||||
if (runner === driver) return driver.transaction((tx) => fn(dbOver(tx, driver)));
|
||||
if (runner === driver)
|
||||
return run(() => driver.transaction((tx) => fn(dbOver(tx, driver, lifecycle, true))));
|
||||
return fn(db);
|
||||
},
|
||||
async createTable(model) {
|
||||
await runner.exec(createTableSql(model, driver.dialect));
|
||||
await run(() => runner.exec(createTableSql(model, driver.dialect)));
|
||||
},
|
||||
close() {
|
||||
return driver.close();
|
||||
if (lifecycle.closePromise) return lifecycle.closePromise;
|
||||
lifecycle.closing = true;
|
||||
lifecycle.closePromise = (async () => {
|
||||
await Promise.allSettled([...lifecycle.active]);
|
||||
await driver.close();
|
||||
})();
|
||||
return lifecycle.closePromise;
|
||||
},
|
||||
};
|
||||
return db;
|
||||
@@ -82,5 +109,5 @@ function dbOver(runner: TxHandle, driver: Driver): Db {
|
||||
|
||||
/** Build a `Db` client from a driver. */
|
||||
export function createDb(driver: Driver): Db {
|
||||
return dbOver(driver, driver);
|
||||
return dbOver(driver, driver, { closing: false, active: new Set() });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user