@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/index.js CHANGED
@@ -294,6 +294,65 @@ const executeInAmbientConnection = async (handle, options) => {
294
294
 
295
295
  //#endregion
296
296
  //#region src/core/connections/transaction.ts
297
+ const transactionNestingCounter = () => {
298
+ let transactionLevel = 0;
299
+ return {
300
+ reset: () => {
301
+ transactionLevel = 0;
302
+ },
303
+ increment: () => {
304
+ transactionLevel++;
305
+ },
306
+ decrement: () => {
307
+ transactionLevel--;
308
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
309
+ },
310
+ get level() {
311
+ return transactionLevel;
312
+ }
313
+ };
314
+ };
315
+ const databaseTransaction = (backend, options) => {
316
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
317
+ const useSavepoints = options?.useSavepoints ?? false;
318
+ const counter = transactionNestingCounter();
319
+ let hasBegun = false;
320
+ return {
321
+ begin: async () => {
322
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
323
+ if (allowNestedTransactions) {
324
+ if (counter.level >= 1) {
325
+ counter.increment();
326
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
327
+ return;
328
+ }
329
+ counter.increment();
330
+ }
331
+ hasBegun = true;
332
+ await backend.begin();
333
+ },
334
+ commit: async () => {
335
+ if (allowNestedTransactions && counter.level > 1) {
336
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
337
+ counter.decrement();
338
+ return;
339
+ }
340
+ if (allowNestedTransactions) counter.reset();
341
+ hasBegun = false;
342
+ await backend.commit();
343
+ },
344
+ rollback: async (error) => {
345
+ if (allowNestedTransactions && counter.level > 1) {
346
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
347
+ counter.decrement();
348
+ return;
349
+ }
350
+ if (allowNestedTransactions) counter.reset();
351
+ hasBegun = false;
352
+ await backend.rollback(error);
353
+ }
354
+ };
355
+ };
297
356
  const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
298
357
  success: true,
299
358
  result: transactionResult
@@ -700,33 +759,80 @@ const createAmbientConnectionPool = (options) => {
700
759
  const createSingletonConnectionPool = (options) => {
701
760
  const { driverType, getConnection } = options;
702
761
  let connectionPromise = null;
762
+ let closed = false;
763
+ const activeOperations = /* @__PURE__ */ new Set();
764
+ const closedError = () => /* @__PURE__ */ new Error("Singleton connection pool has been closed");
765
+ const run = async (operation) => {
766
+ if (closed) throw closedError();
767
+ const activeOperation = operation();
768
+ activeOperations.add(activeOperation);
769
+ try {
770
+ return await activeOperation;
771
+ } finally {
772
+ activeOperations.delete(activeOperation);
773
+ }
774
+ };
703
775
  const getExistingOrNewConnection = () => {
704
776
  if (!connectionPromise) connectionPromise ??= Promise.resolve(getConnection());
705
777
  return connectionPromise;
706
778
  };
779
+ const innerTransactionFactory = transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection);
707
780
  return {
708
781
  driverType,
709
- connection: () => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve())),
710
- execute: sqlExecutorInAmbientConnection({
711
- driverType,
712
- connection: getExistingOrNewConnection
713
- }),
714
- withConnection: (handle, _options) => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection }),
715
- ...transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection),
716
- close: async () => {
782
+ connection: () => run(() => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve()))),
783
+ execute: (() => {
784
+ const ambientExecutor = sqlExecutorInAmbientConnection({
785
+ driverType,
786
+ connection: getExistingOrNewConnection
787
+ });
788
+ return {
789
+ query: (sql, opts) => run(() => ambientExecutor.query(sql, opts)),
790
+ batchQuery: (sqls, opts) => run(() => ambientExecutor.batchQuery(sqls, opts)),
791
+ command: (sql, opts) => run(() => ambientExecutor.command(sql, opts)),
792
+ batchCommand: (sqls, opts) => run(() => ambientExecutor.batchCommand(sqls, opts))
793
+ };
794
+ })(),
795
+ withConnection: (handle, _options) => run(() => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection })),
796
+ transaction: (transactionOptions) => {
797
+ if (closed) throw closedError();
798
+ return innerTransactionFactory.transaction(transactionOptions);
799
+ },
800
+ withTransaction: (handle, transactionOptions) => run(() => innerTransactionFactory.withTransaction(handle, transactionOptions)),
801
+ close: async (closeOptions) => {
802
+ if (closed) return;
803
+ closed = true;
804
+ if (!closeOptions?.force) await Promise.allSettled([...activeOperations]);
717
805
  if (!connectionPromise) return;
718
- await (await connectionPromise).close();
806
+ const connection = await connectionPromise;
807
+ connectionPromise = null;
808
+ await connection.close();
719
809
  }
720
810
  };
721
811
  };
722
812
  const createBoundedConnectionPool = (options) => {
723
813
  const { driverType, maxConnections } = options;
724
- const guardMaxConnections = guardBoundedAccess(options.getConnection, {
814
+ const allConnections = /* @__PURE__ */ new Set();
815
+ const getTrackedConnection = async () => {
816
+ const connection = await options.getConnection();
817
+ allConnections.add(connection);
818
+ return connection;
819
+ };
820
+ const guardMaxConnections = guardBoundedAccess(getTrackedConnection, {
725
821
  maxResources: maxConnections,
726
822
  reuseResources: true
727
823
  });
728
824
  let closed = false;
825
+ const closedError = () => /* @__PURE__ */ new Error("Bounded connection pool has been closed");
826
+ const ensureOpen = () => {
827
+ if (closed) throw closedError();
828
+ };
829
+ const closeAllConnections = async () => {
830
+ const connections = [...allConnections];
831
+ allConnections.clear();
832
+ await Promise.all(connections.map((conn) => conn.close()));
833
+ };
729
834
  const executeWithPooling = async (operation) => {
835
+ ensureOpen();
730
836
  const conn = await guardMaxConnections.acquire();
731
837
  try {
732
838
  return await operation(conn);
@@ -737,6 +843,7 @@ const createBoundedConnectionPool = (options) => {
737
843
  return {
738
844
  driverType,
739
845
  connection: async () => {
846
+ ensureOpen();
740
847
  const conn = await guardMaxConnections.acquire();
741
848
  return wrapPooledConnection(conn, () => Promise.resolve(guardMaxConnections.release(conn)));
742
849
  },
@@ -747,11 +854,20 @@ const createBoundedConnectionPool = (options) => {
747
854
  batchCommand: (sqls, opts) => executeWithPooling((c) => c.execute.batchCommand(sqls, opts))
748
855
  },
749
856
  withConnection: executeWithPooling,
750
- ...transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release),
751
- close: async () => {
857
+ transaction: (transactionOptions) => {
858
+ ensureOpen();
859
+ return transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release).transaction(transactionOptions);
860
+ },
861
+ withTransaction: (handle, transactionOptions) => executeWithPooling((conn) => {
862
+ const withTx = conn.withTransaction;
863
+ return withTx(handle, transactionOptions);
864
+ }),
865
+ close: async (closeOptions) => {
752
866
  if (closed) return;
753
867
  closed = true;
868
+ if (!closeOptions?.force) await guardMaxConnections.waitForIdle();
754
869
  await guardMaxConnections.stop({ force: true });
870
+ await closeAllConnections();
755
871
  }
756
872
  };
757
873
  };
@@ -2382,5 +2498,5 @@ function dumbo(options) {
2382
2498
  }
2383
2499
 
2384
2500
  //#endregion
2385
- export { ANSISQLIdentifierQuote, ANSISQLParamPlaceholder, AdminShutdownError, AutoIncrementSQLColumnToken, BatchCommandNoChangesError, BigIntegerToken, BigSerialToken, CheckViolationError, ColumnTypeToken, ColumnURN, ColumnURNType, ConcurrencyError, ConnectionError, DataError, DatabaseSchemaURN, DatabaseSchemaURNType, DatabaseURN, DatabaseURNType, DeadlockError, DefaultMapSQLParamValueOptions, DumboDatabaseDriverRegistry, DumboDatabaseMetadataRegistry, DumboError, ExclusionViolationError, ExpandArrayProcessor, ExpandSQLInProcessor, ForeignKeyViolationError, FormatIdentifierProcessor, IndexURN, IndexURNType, InsufficientResourcesError, IntegerToken, IntegrityConstraintViolationError, InvalidOperationError, JSONBToken, JSONCodec, JSONParam, JSONReplacer, JSONReplacers, JSONReviver, JSONRevivers, JSONSerializer, LockNotAvailableError, LogLevel, LogStyle, MIGRATIONS_LOCK_ID, MapLiteralProcessor, NoDatabaseLock, NotNullViolationError, ParametrizedSQLBuilder, QueryCanceledError, RawSQL, SQL, SQLArray, SQLColumnToken, SQLColumnTypeTokens, SQLColumnTypeTokensFactory, SQLFormatter, SQLIdentifier, SQLIn, SQLLiteral, SQLPlain, SQLProcessor, SQLProcessorsRegistry, SQLToken, SQLValueMapper, SchemaComponentMigrator, SerialToken, SerializationError, SystemError, TableURN, TableURNType, TimestampToken, TimestamptzToken, TokenizedSQL, TransientDatabaseError, UniqueConstraintError, VarcharToken, ansiSqlReservedMap, canHandleDriverWithConnectionString, color, columnSchemaComponent, combineMigrations, composeJSONReplacers, composeJSONRevivers, count, createAlwaysNewConnectionPool, createAmbientConnection, createAmbientConnectionPool, createBoundedConnectionPool, createConnection, createConnectionPool, createSingletonClientConnectionPool, createSingletonConnection, createSingletonConnectionPool, createTransientConnection, databaseSchemaComponent, databaseSchemaSchemaComponent, defaultDatabaseLockOptions, defaultProcessorsRegistry, describeSQL, dumbo, dumboDatabaseDriverRegistry, dumboDatabaseMetadataRegistry$1 as dumboDatabaseMetadataRegistry, dumboSchema, executeInAmbientConnection, executeInNewConnection, executeInNewDbClient, executeInTransaction, exists, filterSchemaComponentsOfType, findSchemaComponentsOfType, first, firstOrNull, formatSQL, fromDatabaseDriverType, getDatabaseDriverName, getDatabaseMetadata, getDatabaseType, getDefaultDatabase, getDefaultDatabaseAsync, getDefaultMigratorOptionsFromRegistry, getFormatter, indexSchemaComponent, isSQL, isSchemaComponentOfType, isTokenizedSQL, jsonSerializer, mapANSISQLParamPlaceholder, mapColumnToBigint, mapColumnToDate, mapColumnToJSON, mapDefaultSQLColumnProcessors, mapRows, mapSQLIdentifier, mapSQLParamValue, mapSQLQueryResult, mapSchemaComponentsOfType, mapToCamelCase, migrationTableSchemaComponent, parseConnectionString, prettyJson, registerDefaultMigratorOptions, registerFormatter, relationship, resolveDatabaseMetadata, runSQLMigrations, schemaComponent, schemaComponentURN, single, singleOrNull, sqlExecutor, sqlExecutorInAmbientConnection, sqlExecutorInNewConnection, sqlMigration, tableSchemaComponent, toCamelCase, toDatabaseDriverType, tracer, transactionFactoryWithAmbientConnection, transactionFactoryWithAsyncAmbientConnection, transactionFactoryWithDbClient, transactionFactoryWithNewConnection };
2501
+ export { ANSISQLIdentifierQuote, ANSISQLParamPlaceholder, AdminShutdownError, AutoIncrementSQLColumnToken, BatchCommandNoChangesError, BigIntegerToken, BigSerialToken, CheckViolationError, ColumnTypeToken, ColumnURN, ColumnURNType, ConcurrencyError, ConnectionError, DataError, DatabaseSchemaURN, DatabaseSchemaURNType, DatabaseURN, DatabaseURNType, DeadlockError, DefaultMapSQLParamValueOptions, DumboDatabaseDriverRegistry, DumboDatabaseMetadataRegistry, DumboError, ExclusionViolationError, ExpandArrayProcessor, ExpandSQLInProcessor, ForeignKeyViolationError, FormatIdentifierProcessor, IndexURN, IndexURNType, InsufficientResourcesError, IntegerToken, IntegrityConstraintViolationError, InvalidOperationError, JSONBToken, JSONCodec, JSONParam, JSONReplacer, JSONReplacers, JSONReviver, JSONRevivers, JSONSerializer, LockNotAvailableError, LogLevel, LogStyle, MIGRATIONS_LOCK_ID, MapLiteralProcessor, NoDatabaseLock, NotNullViolationError, ParametrizedSQLBuilder, QueryCanceledError, RawSQL, SQL, SQLArray, SQLColumnToken, SQLColumnTypeTokens, SQLColumnTypeTokensFactory, SQLFormatter, SQLIdentifier, SQLIn, SQLLiteral, SQLPlain, SQLProcessor, SQLProcessorsRegistry, SQLToken, SQLValueMapper, SchemaComponentMigrator, SerialToken, SerializationError, SystemError, TableURN, TableURNType, TimestampToken, TimestamptzToken, TokenizedSQL, TransientDatabaseError, UniqueConstraintError, VarcharToken, ansiSqlReservedMap, canHandleDriverWithConnectionString, color, columnSchemaComponent, combineMigrations, composeJSONReplacers, composeJSONRevivers, count, createAlwaysNewConnectionPool, createAmbientConnection, createAmbientConnectionPool, createBoundedConnectionPool, createConnection, createConnectionPool, createSingletonClientConnectionPool, createSingletonConnection, createSingletonConnectionPool, createTransientConnection, databaseSchemaComponent, databaseSchemaSchemaComponent, databaseTransaction, defaultDatabaseLockOptions, defaultProcessorsRegistry, describeSQL, dumbo, dumboDatabaseDriverRegistry, dumboDatabaseMetadataRegistry$1 as dumboDatabaseMetadataRegistry, dumboSchema, executeInAmbientConnection, executeInNewConnection, executeInNewDbClient, executeInTransaction, exists, filterSchemaComponentsOfType, findSchemaComponentsOfType, first, firstOrNull, formatSQL, fromDatabaseDriverType, getDatabaseDriverName, getDatabaseMetadata, getDatabaseType, getDefaultDatabase, getDefaultDatabaseAsync, getDefaultMigratorOptionsFromRegistry, getFormatter, indexSchemaComponent, isSQL, isSchemaComponentOfType, isTokenizedSQL, jsonSerializer, mapANSISQLParamPlaceholder, mapColumnToBigint, mapColumnToDate, mapColumnToJSON, mapDefaultSQLColumnProcessors, mapRows, mapSQLIdentifier, mapSQLParamValue, mapSQLQueryResult, mapSchemaComponentsOfType, mapToCamelCase, migrationTableSchemaComponent, parseConnectionString, prettyJson, registerDefaultMigratorOptions, registerFormatter, relationship, resolveDatabaseMetadata, runSQLMigrations, schemaComponent, schemaComponentURN, single, singleOrNull, sqlExecutor, sqlExecutorInAmbientConnection, sqlExecutorInNewConnection, sqlMigration, tableSchemaComponent, toCamelCase, toDatabaseDriverType, tracer, transactionFactoryWithAmbientConnection, transactionFactoryWithAsyncAmbientConnection, transactionFactoryWithDbClient, transactionFactoryWithNewConnection, transactionNestingCounter };
2386
2502
  //# sourceMappingURL=index.js.map