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

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.
@@ -895,9 +895,12 @@ type InitTransaction<ConnectionType extends AnyConnection = AnyConnection> = (co
895
895
  }) => InferTransactionFromConnection<ConnectionType>;
896
896
  //#endregion
897
897
  //#region src/core/connections/pool.d.ts
898
+ type PoolCloseOptions = {
899
+ force?: boolean;
900
+ };
898
901
  interface ConnectionPool<ConnectionType extends AnyConnection = AnyConnection> extends WithSQLExecutor, WithConnectionFactory<ConnectionType>, WithDatabaseTransactionFactory<ConnectionType> {
899
902
  driverType: ConnectionType['driverType'];
900
- close: () => Promise<void>;
903
+ close: (options?: PoolCloseOptions) => Promise<void>;
901
904
  }
902
905
  //#endregion
903
906
  //#region src/core/index.d.ts
@@ -988,13 +991,6 @@ type SQLitePoolConnectionDefinitionOptions<SQLiteConnectionType extends AnySQLit
988
991
  };
989
992
  type SQLiteConnectionDefinitionOptions<SQLiteConnectionType extends AnySQLitePoolClientConnection = AnySQLitePoolClientConnection, ClientOptions = SQLiteClientOptions> = SQLiteClientConnectionDefinitionOptions<SQLiteConnectionType, ClientOptions> | SQLitePoolConnectionDefinitionOptions<SQLiteConnectionType, ClientOptions>;
990
993
  type SQLiteConnectionFactory<SQLiteConnectionType extends AnySQLiteConnection = AnySQLiteConnection, ConnectionOptions extends SQLiteConnectionOptions = SQLiteConnectionOptions> = (options: ConnectionOptions) => SQLiteConnectionType;
991
- type TransactionNestingCounter = {
992
- increment: () => void;
993
- decrement: () => void;
994
- reset: () => void;
995
- level: number;
996
- };
997
- declare const transactionNestingCounter: () => TransactionNestingCounter;
998
994
  type SqliteAmbientClientConnectionOptions<SQLiteConnectionType extends AnySQLiteClientConnection = AnySQLiteClientConnection> = {
999
995
  driverType: SQLiteConnectionType['driverType'];
1000
996
  client: InferDbClientFromConnection<SQLiteConnectionType>;
@@ -1204,5 +1200,5 @@ type SQLite3DumboConnectionOptions = DumboConnectionOptions<typeof sqlite3DumboD
1204
1200
  connectionString: string | SQLiteConnectionString;
1205
1201
  };
1206
1202
  //#endregion
1207
- export { AnySQLiteClientConnection, AnySQLiteConnection, AnySQLitePoolClientConnection, BatchSQLiteCommandOptions, ConnectionCheckResult, DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLite3Client, SQLite3ClientOptions, SQLite3Connection, SQLite3ConnectionOptions, SQLite3DriverType, SQLite3DumboConnectionOptions, SQLite3DumboOptions, SQLite3PoolOptions, SQLiteAlwaysNewConnectionPool, SQLiteAmbientConnectionPool, SQLiteClient, SQLiteClientConnection, SQLiteClientConnectionDefinitionOptions, SQLiteClientFactory, SQLiteClientOptions, SQLiteClientOrPoolClient, SQLiteCommandOptions, SQLiteConnection, SQLiteConnectionDefinitionOptions, SQLiteConnectionFactory, SQLiteConnectionOptions, SQLiteConnectionString, SQLiteDatabaseName, SQLiteDatabaseType, SQLiteDriverType, SQLiteError, SQLiteErrorMapper, SQLiteFileNameOrConnectionString, SQLiteJSON, SQLiteParameters, SQLitePool, SQLitePoolClient, SQLitePoolClientConnection, SQLitePoolConnectionDefinitionOptions, SQLitePoolFactoryOptions, SQLitePoolOptions, type SQLitePragmaOptions, SQLiteSQLExecutor, SQLiteSingletonConnectionPool, SQLiteTransaction, SQLiteTransactionMode, SQLiteTransactionOptions, Sqlite3Pool, SqliteAmbientClientConnectionOptions, TransactionNestingCounter, checkConnection, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqlite3Client, sqlite3Connection, sqlite3DumboDriver, sqlite3Pool, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, transactionNestingCounter, useSqlite3DumboDriver };
1203
+ export { AnySQLiteClientConnection, AnySQLiteConnection, AnySQLitePoolClientConnection, BatchSQLiteCommandOptions, ConnectionCheckResult, DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLite3Client, SQLite3ClientOptions, SQLite3Connection, SQLite3ConnectionOptions, SQLite3DriverType, SQLite3DumboConnectionOptions, SQLite3DumboOptions, SQLite3PoolOptions, SQLiteAlwaysNewConnectionPool, SQLiteAmbientConnectionPool, SQLiteClient, SQLiteClientConnection, SQLiteClientConnectionDefinitionOptions, SQLiteClientFactory, SQLiteClientOptions, SQLiteClientOrPoolClient, SQLiteCommandOptions, SQLiteConnection, SQLiteConnectionDefinitionOptions, SQLiteConnectionFactory, SQLiteConnectionOptions, SQLiteConnectionString, SQLiteDatabaseName, SQLiteDatabaseType, SQLiteDriverType, SQLiteError, SQLiteErrorMapper, SQLiteFileNameOrConnectionString, SQLiteJSON, SQLiteParameters, SQLitePool, SQLitePoolClient, SQLitePoolClientConnection, SQLitePoolConnectionDefinitionOptions, SQLitePoolFactoryOptions, SQLitePoolOptions, type SQLitePragmaOptions, SQLiteSQLExecutor, SQLiteSingletonConnectionPool, SQLiteTransaction, SQLiteTransactionMode, SQLiteTransactionOptions, Sqlite3Pool, SqliteAmbientClientConnectionOptions, checkConnection, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqlite3Client, sqlite3Connection, sqlite3DumboDriver, sqlite3Pool, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, useSqlite3DumboDriver };
1208
1204
  //# sourceMappingURL=sqlite3.d.cts.map
package/dist/sqlite3.d.ts CHANGED
@@ -895,9 +895,12 @@ type InitTransaction<ConnectionType extends AnyConnection = AnyConnection> = (co
895
895
  }) => InferTransactionFromConnection<ConnectionType>;
896
896
  //#endregion
897
897
  //#region src/core/connections/pool.d.ts
898
+ type PoolCloseOptions = {
899
+ force?: boolean;
900
+ };
898
901
  interface ConnectionPool<ConnectionType extends AnyConnection = AnyConnection> extends WithSQLExecutor, WithConnectionFactory<ConnectionType>, WithDatabaseTransactionFactory<ConnectionType> {
899
902
  driverType: ConnectionType['driverType'];
900
- close: () => Promise<void>;
903
+ close: (options?: PoolCloseOptions) => Promise<void>;
901
904
  }
902
905
  //#endregion
903
906
  //#region src/core/index.d.ts
@@ -988,13 +991,6 @@ type SQLitePoolConnectionDefinitionOptions<SQLiteConnectionType extends AnySQLit
988
991
  };
989
992
  type SQLiteConnectionDefinitionOptions<SQLiteConnectionType extends AnySQLitePoolClientConnection = AnySQLitePoolClientConnection, ClientOptions = SQLiteClientOptions> = SQLiteClientConnectionDefinitionOptions<SQLiteConnectionType, ClientOptions> | SQLitePoolConnectionDefinitionOptions<SQLiteConnectionType, ClientOptions>;
990
993
  type SQLiteConnectionFactory<SQLiteConnectionType extends AnySQLiteConnection = AnySQLiteConnection, ConnectionOptions extends SQLiteConnectionOptions = SQLiteConnectionOptions> = (options: ConnectionOptions) => SQLiteConnectionType;
991
- type TransactionNestingCounter = {
992
- increment: () => void;
993
- decrement: () => void;
994
- reset: () => void;
995
- level: number;
996
- };
997
- declare const transactionNestingCounter: () => TransactionNestingCounter;
998
994
  type SqliteAmbientClientConnectionOptions<SQLiteConnectionType extends AnySQLiteClientConnection = AnySQLiteClientConnection> = {
999
995
  driverType: SQLiteConnectionType['driverType'];
1000
996
  client: InferDbClientFromConnection<SQLiteConnectionType>;
@@ -1204,5 +1200,5 @@ type SQLite3DumboConnectionOptions = DumboConnectionOptions<typeof sqlite3DumboD
1204
1200
  connectionString: string | SQLiteConnectionString;
1205
1201
  };
1206
1202
  //#endregion
1207
- export { AnySQLiteClientConnection, AnySQLiteConnection, AnySQLitePoolClientConnection, BatchSQLiteCommandOptions, ConnectionCheckResult, DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLite3Client, SQLite3ClientOptions, SQLite3Connection, SQLite3ConnectionOptions, SQLite3DriverType, SQLite3DumboConnectionOptions, SQLite3DumboOptions, SQLite3PoolOptions, SQLiteAlwaysNewConnectionPool, SQLiteAmbientConnectionPool, SQLiteClient, SQLiteClientConnection, SQLiteClientConnectionDefinitionOptions, SQLiteClientFactory, SQLiteClientOptions, SQLiteClientOrPoolClient, SQLiteCommandOptions, SQLiteConnection, SQLiteConnectionDefinitionOptions, SQLiteConnectionFactory, SQLiteConnectionOptions, SQLiteConnectionString, SQLiteDatabaseName, SQLiteDatabaseType, SQLiteDriverType, SQLiteError, SQLiteErrorMapper, SQLiteFileNameOrConnectionString, SQLiteJSON, SQLiteParameters, SQLitePool, SQLitePoolClient, SQLitePoolClientConnection, SQLitePoolConnectionDefinitionOptions, SQLitePoolFactoryOptions, SQLitePoolOptions, type SQLitePragmaOptions, SQLiteSQLExecutor, SQLiteSingletonConnectionPool, SQLiteTransaction, SQLiteTransactionMode, SQLiteTransactionOptions, Sqlite3Pool, SqliteAmbientClientConnectionOptions, TransactionNestingCounter, checkConnection, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqlite3Client, sqlite3Connection, sqlite3DumboDriver, sqlite3Pool, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, transactionNestingCounter, useSqlite3DumboDriver };
1203
+ export { AnySQLiteClientConnection, AnySQLiteConnection, AnySQLitePoolClientConnection, BatchSQLiteCommandOptions, ConnectionCheckResult, DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLite3Client, SQLite3ClientOptions, SQLite3Connection, SQLite3ConnectionOptions, SQLite3DriverType, SQLite3DumboConnectionOptions, SQLite3DumboOptions, SQLite3PoolOptions, SQLiteAlwaysNewConnectionPool, SQLiteAmbientConnectionPool, SQLiteClient, SQLiteClientConnection, SQLiteClientConnectionDefinitionOptions, SQLiteClientFactory, SQLiteClientOptions, SQLiteClientOrPoolClient, SQLiteCommandOptions, SQLiteConnection, SQLiteConnectionDefinitionOptions, SQLiteConnectionFactory, SQLiteConnectionOptions, SQLiteConnectionString, SQLiteDatabaseName, SQLiteDatabaseType, SQLiteDriverType, SQLiteError, SQLiteErrorMapper, SQLiteFileNameOrConnectionString, SQLiteJSON, SQLiteParameters, SQLitePool, SQLitePoolClient, SQLitePoolClientConnection, SQLitePoolConnectionDefinitionOptions, SQLitePoolFactoryOptions, SQLitePoolOptions, type SQLitePragmaOptions, SQLiteSQLExecutor, SQLiteSingletonConnectionPool, SQLiteTransaction, SQLiteTransactionMode, SQLiteTransactionOptions, Sqlite3Pool, SqliteAmbientClientConnectionOptions, checkConnection, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqlite3Client, sqlite3Connection, sqlite3DumboDriver, sqlite3Pool, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, useSqlite3DumboDriver };
1208
1204
  //# sourceMappingURL=sqlite3.d.ts.map
package/dist/sqlite3.js CHANGED
@@ -243,6 +243,65 @@ const executeInAmbientConnection = async (handle, options) => {
243
243
 
244
244
  //#endregion
245
245
  //#region src/core/connections/transaction.ts
246
+ const transactionNestingCounter = () => {
247
+ let transactionLevel = 0;
248
+ return {
249
+ reset: () => {
250
+ transactionLevel = 0;
251
+ },
252
+ increment: () => {
253
+ transactionLevel++;
254
+ },
255
+ decrement: () => {
256
+ transactionLevel--;
257
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
258
+ },
259
+ get level() {
260
+ return transactionLevel;
261
+ }
262
+ };
263
+ };
264
+ const databaseTransaction = (backend, options) => {
265
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
266
+ const useSavepoints = options?.useSavepoints ?? false;
267
+ const counter = transactionNestingCounter();
268
+ let hasBegun = false;
269
+ return {
270
+ begin: async () => {
271
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
272
+ if (allowNestedTransactions) {
273
+ if (counter.level >= 1) {
274
+ counter.increment();
275
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
276
+ return;
277
+ }
278
+ counter.increment();
279
+ }
280
+ hasBegun = true;
281
+ await backend.begin();
282
+ },
283
+ commit: async () => {
284
+ if (allowNestedTransactions && counter.level > 1) {
285
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
286
+ counter.decrement();
287
+ return;
288
+ }
289
+ if (allowNestedTransactions) counter.reset();
290
+ hasBegun = false;
291
+ await backend.commit();
292
+ },
293
+ rollback: async (error) => {
294
+ if (allowNestedTransactions && counter.level > 1) {
295
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
296
+ counter.decrement();
297
+ return;
298
+ }
299
+ if (allowNestedTransactions) counter.reset();
300
+ hasBegun = false;
301
+ await backend.rollback(error);
302
+ }
303
+ };
304
+ };
246
305
  const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
247
306
  success: true,
248
307
  result: transactionResult
@@ -636,33 +695,80 @@ const createAmbientConnectionPool = (options) => {
636
695
  const createSingletonConnectionPool = (options) => {
637
696
  const { driverType, getConnection } = options;
638
697
  let connectionPromise = null;
698
+ let closed = false;
699
+ const activeOperations = /* @__PURE__ */ new Set();
700
+ const closedError = () => /* @__PURE__ */ new Error("Singleton connection pool has been closed");
701
+ const run = async (operation) => {
702
+ if (closed) throw closedError();
703
+ const activeOperation = operation();
704
+ activeOperations.add(activeOperation);
705
+ try {
706
+ return await activeOperation;
707
+ } finally {
708
+ activeOperations.delete(activeOperation);
709
+ }
710
+ };
639
711
  const getExistingOrNewConnection = () => {
640
712
  if (!connectionPromise) connectionPromise ??= Promise.resolve(getConnection());
641
713
  return connectionPromise;
642
714
  };
715
+ const innerTransactionFactory = transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection);
643
716
  return {
644
717
  driverType,
645
- connection: () => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve())),
646
- execute: sqlExecutorInAmbientConnection({
647
- driverType,
648
- connection: getExistingOrNewConnection
649
- }),
650
- withConnection: (handle, _options) => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection }),
651
- ...transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection),
652
- close: async () => {
718
+ connection: () => run(() => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve()))),
719
+ execute: (() => {
720
+ const ambientExecutor = sqlExecutorInAmbientConnection({
721
+ driverType,
722
+ connection: getExistingOrNewConnection
723
+ });
724
+ return {
725
+ query: (sql, opts) => run(() => ambientExecutor.query(sql, opts)),
726
+ batchQuery: (sqls, opts) => run(() => ambientExecutor.batchQuery(sqls, opts)),
727
+ command: (sql, opts) => run(() => ambientExecutor.command(sql, opts)),
728
+ batchCommand: (sqls, opts) => run(() => ambientExecutor.batchCommand(sqls, opts))
729
+ };
730
+ })(),
731
+ withConnection: (handle, _options) => run(() => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection })),
732
+ transaction: (transactionOptions) => {
733
+ if (closed) throw closedError();
734
+ return innerTransactionFactory.transaction(transactionOptions);
735
+ },
736
+ withTransaction: (handle, transactionOptions) => run(() => innerTransactionFactory.withTransaction(handle, transactionOptions)),
737
+ close: async (closeOptions) => {
738
+ if (closed) return;
739
+ closed = true;
740
+ if (!closeOptions?.force) await Promise.allSettled([...activeOperations]);
653
741
  if (!connectionPromise) return;
654
- await (await connectionPromise).close();
742
+ const connection = await connectionPromise;
743
+ connectionPromise = null;
744
+ await connection.close();
655
745
  }
656
746
  };
657
747
  };
658
748
  const createBoundedConnectionPool = (options) => {
659
749
  const { driverType, maxConnections } = options;
660
- const guardMaxConnections = guardBoundedAccess(options.getConnection, {
750
+ const allConnections = /* @__PURE__ */ new Set();
751
+ const getTrackedConnection = async () => {
752
+ const connection = await options.getConnection();
753
+ allConnections.add(connection);
754
+ return connection;
755
+ };
756
+ const guardMaxConnections = guardBoundedAccess(getTrackedConnection, {
661
757
  maxResources: maxConnections,
662
758
  reuseResources: true
663
759
  });
664
760
  let closed = false;
761
+ const closedError = () => /* @__PURE__ */ new Error("Bounded connection pool has been closed");
762
+ const ensureOpen = () => {
763
+ if (closed) throw closedError();
764
+ };
765
+ const closeAllConnections = async () => {
766
+ const connections = [...allConnections];
767
+ allConnections.clear();
768
+ await Promise.all(connections.map((conn) => conn.close()));
769
+ };
665
770
  const executeWithPooling = async (operation) => {
771
+ ensureOpen();
666
772
  const conn = await guardMaxConnections.acquire();
667
773
  try {
668
774
  return await operation(conn);
@@ -673,6 +779,7 @@ const createBoundedConnectionPool = (options) => {
673
779
  return {
674
780
  driverType,
675
781
  connection: async () => {
782
+ ensureOpen();
676
783
  const conn = await guardMaxConnections.acquire();
677
784
  return wrapPooledConnection(conn, () => Promise.resolve(guardMaxConnections.release(conn)));
678
785
  },
@@ -683,11 +790,20 @@ const createBoundedConnectionPool = (options) => {
683
790
  batchCommand: (sqls, opts) => executeWithPooling((c) => c.execute.batchCommand(sqls, opts))
684
791
  },
685
792
  withConnection: executeWithPooling,
686
- ...transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release),
687
- close: async () => {
793
+ transaction: (transactionOptions) => {
794
+ ensureOpen();
795
+ return transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release).transaction(transactionOptions);
796
+ },
797
+ withTransaction: (handle, transactionOptions) => executeWithPooling((conn) => {
798
+ const withTx = conn.withTransaction;
799
+ return withTx(handle, transactionOptions);
800
+ }),
801
+ close: async (closeOptions) => {
688
802
  if (closed) return;
689
803
  closed = true;
804
+ if (!closeOptions?.force) await guardMaxConnections.waitForIdle();
690
805
  await guardMaxConnections.stop({ force: true });
806
+ await closeAllConnections();
691
807
  }
692
808
  };
693
809
  };
@@ -2045,54 +2161,46 @@ const sqliteSQLExecutor = (driverType, serializer, formatter, errorMapper) => ({
2045
2161
  //#endregion
2046
2162
  //#region src/storage/sqlite/core/transactions/index.ts
2047
2163
  const sqliteTransaction = (driverType, connection, allowNestedTransactions, serializer, defaultTransactionMode) => (getClient, options) => {
2048
- const transactionCounter = transactionNestingCounter();
2049
2164
  allowNestedTransactions = options?.allowNestedTransactions ?? allowNestedTransactions;
2050
- let hasBegun = false;
2051
- return {
2052
- connection: connection(),
2053
- driverType,
2054
- begin: async function() {
2165
+ const useSavepoints = options?.useSavepoints ?? false;
2166
+ const tx = databaseTransaction({
2167
+ begin: async () => {
2055
2168
  const client = await getClient;
2056
- if (allowNestedTransactions) {
2057
- if (transactionCounter.level >= 1) {
2058
- transactionCounter.increment();
2059
- if (options?.useSavepoints) await client.command(SQL`SAVEPOINT transaction${SQL.plain(transactionCounter.level.toString())}`);
2060
- return;
2061
- }
2062
- transactionCounter.increment();
2063
- } else if (hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
2064
- hasBegun = true;
2065
2169
  const mode = options?.mode ?? defaultTransactionMode ?? "IMMEDIATE";
2066
2170
  await client.command(SQL`BEGIN ${SQL.plain(mode)} TRANSACTION`);
2067
2171
  },
2068
- commit: async function() {
2172
+ commit: async () => {
2069
2173
  const client = await getClient;
2070
- if (allowNestedTransactions && transactionCounter.level > 1) {
2071
- if (options?.useSavepoints) await client.command(SQL`RELEASE transaction${SQL.plain(transactionCounter.level.toString())}`);
2072
- transactionCounter.decrement();
2073
- return;
2074
- }
2075
2174
  try {
2076
- if (allowNestedTransactions) transactionCounter.reset();
2077
- hasBegun = false;
2078
2175
  await client.command(SQL`COMMIT`);
2079
2176
  } finally {
2080
- if (options?.close) await options?.close(client);
2177
+ if (options?.close) await options.close(client);
2081
2178
  }
2082
2179
  },
2083
- rollback: async function(error) {
2180
+ rollback: async (error) => {
2084
2181
  const client = await getClient;
2085
- if (allowNestedTransactions && transactionCounter.level > 1) {
2086
- transactionCounter.decrement();
2087
- return;
2088
- }
2089
2182
  try {
2090
- hasBegun = false;
2091
2183
  await client.command(SQL`ROLLBACK`);
2092
2184
  } finally {
2093
- if (options?.close) await options?.close(client, error);
2185
+ if (options?.close) await options.close(client, error);
2094
2186
  }
2095
2187
  },
2188
+ savepoint: async (level) => {
2189
+ await (await getClient).command(SQL`SAVEPOINT transaction${SQL.plain(level.toString())}`);
2190
+ },
2191
+ releaseSavepoint: async (level) => {
2192
+ await (await getClient).command(SQL`RELEASE transaction${SQL.plain(level.toString())}`);
2193
+ }
2194
+ }, {
2195
+ allowNestedTransactions,
2196
+ useSavepoints
2197
+ });
2198
+ return {
2199
+ connection: connection(),
2200
+ driverType,
2201
+ begin: tx.begin,
2202
+ commit: tx.commit,
2203
+ rollback: tx.rollback,
2096
2204
  execute: sqlExecutor(sqliteSQLExecutor(driverType, serializer), { connect: () => getClient }),
2097
2205
  _transactionOptions: {
2098
2206
  ...options,
@@ -2138,24 +2246,6 @@ const isSQLiteError = (error) => {
2138
2246
  if (error instanceof Error && "code" in error) return true;
2139
2247
  return false;
2140
2248
  };
2141
- const transactionNestingCounter = () => {
2142
- let transactionLevel = 0;
2143
- return {
2144
- reset: () => {
2145
- transactionLevel = 0;
2146
- },
2147
- increment: () => {
2148
- transactionLevel++;
2149
- },
2150
- decrement: () => {
2151
- transactionLevel--;
2152
- if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
2153
- },
2154
- get level() {
2155
- return transactionLevel;
2156
- }
2157
- };
2158
- };
2159
2249
  const sqliteAmbientClientConnection = (options) => {
2160
2250
  const { client, driverType, initTransaction, allowNestedTransactions, defaultTransactionMode, serializer, errorMapper } = options;
2161
2251
  return createAmbientConnection({
@@ -2581,7 +2671,9 @@ const sqlite3Connection = (options) => sqliteConnection({
2581
2671
 
2582
2672
  //#endregion
2583
2673
  //#region src/storage/sqlite/sqlite3/pool/singletonPool.ts
2674
+ const DEFAULT_SQLITE_MAX_TASK_IDLE_TIME_MS = 3e4;
2584
2675
  const sqlite3SingletonPool = (options) => {
2676
+ const maxTaskIdleTime = options.maxTaskIdleTime ?? 3e4;
2585
2677
  const inner = createSingletonConnectionPool({
2586
2678
  driverType: options.driverType,
2587
2679
  getConnection: options.getConnection,
@@ -2589,7 +2681,8 @@ const sqlite3SingletonPool = (options) => {
2589
2681
  });
2590
2682
  const taskProcessor = new TaskProcessor({
2591
2683
  maxActiveTasks: 1,
2592
- maxQueueSize: options.maxQueueSize ?? 1e3
2684
+ maxQueueSize: options.maxQueueSize ?? 1e3,
2685
+ maxTaskIdleTime
2593
2686
  });
2594
2687
  const insideWriterTask = new AsyncLocalStorage();
2595
2688
  const enqueue = (op) => {
@@ -2614,9 +2707,9 @@ const sqlite3SingletonPool = (options) => {
2614
2707
  command: (sql, commandOptions) => enqueue(() => inner.execute.command(sql, commandOptions)),
2615
2708
  batchCommand: (sqls, commandOptions) => enqueue(() => inner.execute.batchCommand(sqls, commandOptions))
2616
2709
  },
2617
- close: async () => {
2618
- await taskProcessor.stop();
2619
- await inner.close();
2710
+ close: async (closeOptions) => {
2711
+ await taskProcessor.stop({ ...closeOptions?.force ? { force: true } : {} });
2712
+ await inner.close(closeOptions);
2620
2713
  }
2621
2714
  };
2622
2715
  };
@@ -2661,7 +2754,8 @@ const sqliteDualConnectionPool = (options) => {
2661
2754
  };
2662
2755
  const writerPool = sqlite3SingletonPool({
2663
2756
  driverType: options.driverType,
2664
- getConnection: () => wrappedConnectionFactory(false, connectionOptions)
2757
+ getConnection: () => wrappedConnectionFactory(false, connectionOptions),
2758
+ ...options.maxTaskIdleTime !== void 0 ? { maxTaskIdleTime: options.maxTaskIdleTime } : {}
2665
2759
  });
2666
2760
  const readerPool = createBoundedConnectionPool({
2667
2761
  driverType: options.driverType,
@@ -2698,18 +2792,26 @@ const sqlite3Pool = (options) => {
2698
2792
  ...opts,
2699
2793
  serializer: options.serializer ?? JSONSerializer
2700
2794
  });
2701
- if (isInMemoryDatabase(options) || "client" in options && Boolean(options.client) || options.singleton === true) return sqlite3SingletonPool({
2795
+ const isSingleton = isInMemoryDatabase(options) || "client" in options && Boolean(options.client) || options.singleton === true;
2796
+ const lifecycleOptions = extractLifecycleOptions(options);
2797
+ if (isSingleton) return sqlite3SingletonPool({
2702
2798
  driverType: SQLite3DriverType,
2703
- getConnection: () => sqliteConnectionFactory(options)
2799
+ getConnection: () => sqliteConnectionFactory(options),
2800
+ ...lifecycleOptions
2704
2801
  });
2705
2802
  const readerPoolSize = options.readerPoolSize;
2706
2803
  return sqliteDualConnectionPool({
2707
2804
  driverType: SQLite3DriverType,
2708
2805
  sqliteConnectionFactory,
2709
2806
  connectionOptions: options,
2710
- ...readerPoolSize !== void 0 ? { readerPoolSize } : {}
2807
+ ...readerPoolSize !== void 0 ? { readerPoolSize } : {},
2808
+ ...lifecycleOptions
2711
2809
  });
2712
2810
  };
2811
+ const extractLifecycleOptions = (options) => {
2812
+ const lifecycle = options;
2813
+ return { ...lifecycle.maxTaskIdleTime !== void 0 ? { maxTaskIdleTime: lifecycle.maxTaskIdleTime } : {} };
2814
+ };
2713
2815
  const tryParseConnectionString = (connectionString) => {
2714
2816
  try {
2715
2817
  return SQLiteConnectionString(connectionString);
@@ -2731,5 +2833,5 @@ const useSqlite3DumboDriver = () => {
2731
2833
  useSqlite3DumboDriver();
2732
2834
 
2733
2835
  //#endregion
2734
- export { DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLite3DriverType, SQLiteConnectionString, SQLiteDatabaseName, SQLiteJSON, checkConnection, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqlite3Client, sqlite3Connection, sqlite3DumboDriver, sqlite3Pool, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, transactionNestingCounter, useSqlite3DumboDriver };
2836
+ export { DEFAULT_SQLITE_PRAGMA_OPTIONS, DefaultSQLiteMigratorOptions, InMemorySQLiteDatabase, SQLite3DriverType, SQLiteConnectionString, SQLiteDatabaseName, SQLiteJSON, checkConnection, defaultSQLiteDatabase, isInMemoryDatabase, isSQLiteError, mapSqliteError, parsePragmasFromConnectionString, sqlite3Client, sqlite3Connection, sqlite3DumboDriver, sqlite3Pool, sqliteAlwaysNewConnectionPool, sqliteAmbientClientConnection, sqliteAmbientConnectionPool, sqliteClientConnection, sqliteConnection, sqliteExecute, sqliteFormatter, sqliteMetadata, sqlitePool, sqlitePoolClientConnection, sqliteSQLExecutor, sqliteSingletonConnectionPool, sqliteTransaction, tableExists, toSqlitePoolOptions, useSqlite3DumboDriver };
2735
2837
  //# sourceMappingURL=sqlite3.js.map