@event-driven-io/dumbo 0.13.0-beta.43 → 0.13.0-beta.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sqlite.js CHANGED
@@ -225,6 +225,65 @@ const executeInAmbientConnection = async (handle, options) => {
225
225
 
226
226
  //#endregion
227
227
  //#region src/core/connections/transaction.ts
228
+ const transactionNestingCounter = () => {
229
+ let transactionLevel = 0;
230
+ return {
231
+ reset: () => {
232
+ transactionLevel = 0;
233
+ },
234
+ increment: () => {
235
+ transactionLevel++;
236
+ },
237
+ decrement: () => {
238
+ transactionLevel--;
239
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
240
+ },
241
+ get level() {
242
+ return transactionLevel;
243
+ }
244
+ };
245
+ };
246
+ const databaseTransaction = (backend, options) => {
247
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
248
+ const useSavepoints = options?.useSavepoints ?? false;
249
+ const counter = transactionNestingCounter();
250
+ let hasBegun = false;
251
+ return {
252
+ begin: async () => {
253
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
254
+ if (allowNestedTransactions) {
255
+ if (counter.level >= 1) {
256
+ counter.increment();
257
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
258
+ return;
259
+ }
260
+ counter.increment();
261
+ }
262
+ hasBegun = true;
263
+ await backend.begin();
264
+ },
265
+ commit: async () => {
266
+ if (allowNestedTransactions && counter.level > 1) {
267
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
268
+ counter.decrement();
269
+ return;
270
+ }
271
+ if (allowNestedTransactions) counter.reset();
272
+ hasBegun = false;
273
+ await backend.commit();
274
+ },
275
+ rollback: async (error) => {
276
+ if (allowNestedTransactions && counter.level > 1) {
277
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
278
+ counter.decrement();
279
+ return;
280
+ }
281
+ if (allowNestedTransactions) counter.reset();
282
+ hasBegun = false;
283
+ await backend.rollback(error);
284
+ }
285
+ };
286
+ };
228
287
  const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
229
288
  success: true,
230
289
  result: transactionResult
@@ -415,22 +474,53 @@ const createAmbientConnectionPool = (options) => {
415
474
  const createSingletonConnectionPool = (options) => {
416
475
  const { driverType, getConnection } = options;
417
476
  let connectionPromise = null;
477
+ let closed = false;
478
+ const activeOperations = /* @__PURE__ */ new Set();
479
+ const closedError = () => /* @__PURE__ */ new Error("Singleton connection pool has been closed");
480
+ const run = async (operation) => {
481
+ if (closed) throw closedError();
482
+ const activeOperation = operation();
483
+ activeOperations.add(activeOperation);
484
+ try {
485
+ return await activeOperation;
486
+ } finally {
487
+ activeOperations.delete(activeOperation);
488
+ }
489
+ };
418
490
  const getExistingOrNewConnection = () => {
419
491
  if (!connectionPromise) connectionPromise ??= Promise.resolve(getConnection());
420
492
  return connectionPromise;
421
493
  };
494
+ const innerTransactionFactory = transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection);
422
495
  return {
423
496
  driverType,
424
- connection: () => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve())),
425
- execute: sqlExecutorInAmbientConnection({
426
- driverType,
427
- connection: getExistingOrNewConnection
428
- }),
429
- withConnection: (handle, _options) => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection }),
430
- ...transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection),
431
- close: async () => {
497
+ connection: () => run(() => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve()))),
498
+ execute: (() => {
499
+ const ambientExecutor = sqlExecutorInAmbientConnection({
500
+ driverType,
501
+ connection: getExistingOrNewConnection
502
+ });
503
+ return {
504
+ query: (sql, opts) => run(() => ambientExecutor.query(sql, opts)),
505
+ batchQuery: (sqls, opts) => run(() => ambientExecutor.batchQuery(sqls, opts)),
506
+ command: (sql, opts) => run(() => ambientExecutor.command(sql, opts)),
507
+ batchCommand: (sqls, opts) => run(() => ambientExecutor.batchCommand(sqls, opts))
508
+ };
509
+ })(),
510
+ withConnection: (handle, _options) => run(() => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection })),
511
+ transaction: (transactionOptions) => {
512
+ if (closed) throw closedError();
513
+ return innerTransactionFactory.transaction(transactionOptions);
514
+ },
515
+ withTransaction: (handle, transactionOptions) => run(() => innerTransactionFactory.withTransaction(handle, transactionOptions)),
516
+ close: async (closeOptions) => {
517
+ if (closed) return;
518
+ closed = true;
519
+ if (!closeOptions?.force) await Promise.allSettled([...activeOperations]);
432
520
  if (!connectionPromise) return;
433
- await (await connectionPromise).close();
521
+ const connection = await connectionPromise;
522
+ connectionPromise = null;
523
+ await connection.close();
434
524
  }
435
525
  };
436
526
  };
@@ -1783,54 +1873,46 @@ const sqliteSQLExecutor = (driverType, serializer, formatter, errorMapper) => ({
1783
1873
  //#endregion
1784
1874
  //#region src/storage/sqlite/core/transactions/index.ts
1785
1875
  const sqliteTransaction = (driverType, connection, allowNestedTransactions, serializer, defaultTransactionMode) => (getClient, options) => {
1786
- const transactionCounter = transactionNestingCounter();
1787
1876
  allowNestedTransactions = options?.allowNestedTransactions ?? allowNestedTransactions;
1788
- let hasBegun = false;
1789
- return {
1790
- connection: connection(),
1791
- driverType,
1792
- begin: async function() {
1877
+ const useSavepoints = options?.useSavepoints ?? false;
1878
+ const tx = databaseTransaction({
1879
+ begin: async () => {
1793
1880
  const client = await getClient;
1794
- if (allowNestedTransactions) {
1795
- if (transactionCounter.level >= 1) {
1796
- transactionCounter.increment();
1797
- if (options?.useSavepoints) await client.command(SQL`SAVEPOINT transaction${SQL.plain(transactionCounter.level.toString())}`);
1798
- return;
1799
- }
1800
- transactionCounter.increment();
1801
- } else if (hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
1802
- hasBegun = true;
1803
1881
  const mode = options?.mode ?? defaultTransactionMode ?? "IMMEDIATE";
1804
1882
  await client.command(SQL`BEGIN ${SQL.plain(mode)} TRANSACTION`);
1805
1883
  },
1806
- commit: async function() {
1884
+ commit: async () => {
1807
1885
  const client = await getClient;
1808
- if (allowNestedTransactions && transactionCounter.level > 1) {
1809
- if (options?.useSavepoints) await client.command(SQL`RELEASE transaction${SQL.plain(transactionCounter.level.toString())}`);
1810
- transactionCounter.decrement();
1811
- return;
1812
- }
1813
1886
  try {
1814
- if (allowNestedTransactions) transactionCounter.reset();
1815
- hasBegun = false;
1816
1887
  await client.command(SQL`COMMIT`);
1817
1888
  } finally {
1818
- if (options?.close) await options?.close(client);
1889
+ if (options?.close) await options.close(client);
1819
1890
  }
1820
1891
  },
1821
- rollback: async function(error) {
1892
+ rollback: async (error) => {
1822
1893
  const client = await getClient;
1823
- if (allowNestedTransactions && transactionCounter.level > 1) {
1824
- transactionCounter.decrement();
1825
- return;
1826
- }
1827
1894
  try {
1828
- hasBegun = false;
1829
1895
  await client.command(SQL`ROLLBACK`);
1830
1896
  } finally {
1831
- if (options?.close) await options?.close(client, error);
1897
+ if (options?.close) await options.close(client, error);
1832
1898
  }
1833
1899
  },
1900
+ savepoint: async (level) => {
1901
+ await (await getClient).command(SQL`SAVEPOINT transaction${SQL.plain(level.toString())}`);
1902
+ },
1903
+ releaseSavepoint: async (level) => {
1904
+ await (await getClient).command(SQL`RELEASE transaction${SQL.plain(level.toString())}`);
1905
+ }
1906
+ }, {
1907
+ allowNestedTransactions,
1908
+ useSavepoints
1909
+ });
1910
+ return {
1911
+ connection: connection(),
1912
+ driverType,
1913
+ begin: tx.begin,
1914
+ commit: tx.commit,
1915
+ rollback: tx.rollback,
1834
1916
  execute: sqlExecutor(sqliteSQLExecutor(driverType, serializer), { connect: () => getClient }),
1835
1917
  _transactionOptions: {
1836
1918
  ...options,
@@ -1876,24 +1958,6 @@ const isSQLiteError = (error) => {
1876
1958
  if (error instanceof Error && "code" in error) return true;
1877
1959
  return false;
1878
1960
  };
1879
- const transactionNestingCounter = () => {
1880
- let transactionLevel = 0;
1881
- return {
1882
- reset: () => {
1883
- transactionLevel = 0;
1884
- },
1885
- increment: () => {
1886
- transactionLevel++;
1887
- },
1888
- decrement: () => {
1889
- transactionLevel--;
1890
- if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
1891
- },
1892
- get level() {
1893
- return transactionLevel;
1894
- }
1895
- };
1896
- };
1897
1961
  const sqliteAmbientClientConnection = (options) => {
1898
1962
  const { client, driverType, initTransaction, allowNestedTransactions, defaultTransactionMode, serializer, errorMapper } = options;
1899
1963
  return createAmbientConnection({
@@ -2066,5 +2130,5 @@ const SQLiteJSON = { path };
2066
2130
  const SQLiteDatabaseName = "SQLite";
2067
2131
 
2068
2132
  //#endregion
2069
- export { DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLiteConnectionString, SQLiteDatabaseName, SQLiteJSON, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, transactionNestingCounter };
2133
+ export { DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLiteConnectionString, SQLiteDatabaseName, SQLiteJSON, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions };
2070
2134
  //# sourceMappingURL=sqlite.js.map