@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/pg.cjs CHANGED
@@ -376,6 +376,65 @@ const executeInNewConnection = async (handle, options) => {
376
376
 
377
377
  //#endregion
378
378
  //#region src/core/connections/transaction.ts
379
+ const transactionNestingCounter = () => {
380
+ let transactionLevel = 0;
381
+ return {
382
+ reset: () => {
383
+ transactionLevel = 0;
384
+ },
385
+ increment: () => {
386
+ transactionLevel++;
387
+ },
388
+ decrement: () => {
389
+ transactionLevel--;
390
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
391
+ },
392
+ get level() {
393
+ return transactionLevel;
394
+ }
395
+ };
396
+ };
397
+ const databaseTransaction = (backend, options) => {
398
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
399
+ const useSavepoints = options?.useSavepoints ?? false;
400
+ const counter = transactionNestingCounter();
401
+ let hasBegun = false;
402
+ return {
403
+ begin: async () => {
404
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
405
+ if (allowNestedTransactions) {
406
+ if (counter.level >= 1) {
407
+ counter.increment();
408
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
409
+ return;
410
+ }
411
+ counter.increment();
412
+ }
413
+ hasBegun = true;
414
+ await backend.begin();
415
+ },
416
+ commit: async () => {
417
+ if (allowNestedTransactions && counter.level > 1) {
418
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
419
+ counter.decrement();
420
+ return;
421
+ }
422
+ if (allowNestedTransactions) counter.reset();
423
+ hasBegun = false;
424
+ await backend.commit();
425
+ },
426
+ rollback: async (error) => {
427
+ if (allowNestedTransactions && counter.level > 1) {
428
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
429
+ counter.decrement();
430
+ return;
431
+ }
432
+ if (allowNestedTransactions) counter.reset();
433
+ hasBegun = false;
434
+ await backend.rollback(error);
435
+ }
436
+ };
437
+ };
379
438
  const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
380
439
  success: true,
381
440
  result: transactionResult
@@ -2082,57 +2141,92 @@ async function batchCommand(client, sqls, serializer, options) {
2082
2141
 
2083
2142
  //#endregion
2084
2143
  //#region src/storage/postgresql/pg/connections/transaction.ts
2085
- const pgTransaction = (connection, serializer) => (getClient, options) => ({
2086
- connection: connection(),
2087
- driverType: PgDriverType,
2088
- begin: async () => {
2089
- const client = await getClient;
2090
- const parts = ["BEGIN"];
2091
- if (options?.isolationLevel) parts.push(`ISOLATION LEVEL ${options.isolationLevel}`);
2092
- if (options?.readonly) parts.push("READ ONLY");
2093
- await client.query(parts.join(" "));
2094
- },
2095
- commit: async () => {
2096
- const client = await getClient;
2097
- try {
2098
- await client.query("COMMIT");
2099
- } finally {
2100
- if (options?.close) await options?.close(client);
2144
+ const pgTransaction = (connection, serializer) => (getClient, options) => {
2145
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
2146
+ const tx = databaseTransaction({
2147
+ begin: async () => {
2148
+ const client = await getClient;
2149
+ const parts = ["BEGIN"];
2150
+ if (options?.isolationLevel) parts.push(`ISOLATION LEVEL ${options.isolationLevel}`);
2151
+ if (options?.readonly) parts.push("READ ONLY");
2152
+ await client.query(parts.join(" "));
2153
+ },
2154
+ commit: async () => {
2155
+ const client = await getClient;
2156
+ try {
2157
+ await client.query("COMMIT");
2158
+ } finally {
2159
+ if (options?.close) await options.close(client);
2160
+ }
2161
+ },
2162
+ rollback: async (error) => {
2163
+ const client = await getClient;
2164
+ try {
2165
+ await client.query("ROLLBACK");
2166
+ } finally {
2167
+ if (options?.close) await options.close(client, error);
2168
+ }
2169
+ },
2170
+ savepoint: async (level) => {
2171
+ await (await getClient).query(`SAVEPOINT pg_savepoint_${level}`);
2172
+ },
2173
+ releaseSavepoint: async (level) => {
2174
+ await (await getClient).query(`RELEASE SAVEPOINT pg_savepoint_${level}`);
2175
+ },
2176
+ rollbackToSavepoint: async (level) => {
2177
+ await (await getClient).query(`ROLLBACK TO SAVEPOINT pg_savepoint_${level}`);
2101
2178
  }
2102
- },
2103
- rollback: async (error) => {
2104
- const client = await getClient;
2105
- try {
2106
- await client.query("ROLLBACK");
2107
- } finally {
2108
- if (options?.close) await options?.close(client, error);
2179
+ }, {
2180
+ allowNestedTransactions,
2181
+ useSavepoints: options?.useSavepoints ?? false
2182
+ });
2183
+ return {
2184
+ connection: connection(),
2185
+ driverType: PgDriverType,
2186
+ begin: tx.begin,
2187
+ commit: tx.commit,
2188
+ rollback: tx.rollback,
2189
+ execute: sqlExecutor(pgSQLExecutor({ serializer }), { connect: () => getClient }),
2190
+ _transactionOptions: {
2191
+ ...options ?? {},
2192
+ allowNestedTransactions
2109
2193
  }
2110
- },
2111
- execute: sqlExecutor(pgSQLExecutor({ serializer }), { connect: () => getClient }),
2112
- _transactionOptions: options ?? {}
2113
- });
2194
+ };
2195
+ };
2114
2196
 
2115
2197
  //#endregion
2116
2198
  //#region src/storage/postgresql/pg/connections/connection.ts
2117
2199
  const PgDriverType = "PostgreSQL:pg";
2118
2200
  const pgClientConnection = (options) => {
2119
- const { connect, close } = options;
2201
+ const { connect, close, transactionOptions } = options;
2120
2202
  return createConnection({
2121
2203
  driverType: PgDriverType,
2122
2204
  connect,
2123
2205
  close,
2124
- initTransaction: (connection) => pgTransaction(connection, options.serializer),
2206
+ initTransaction: (connection) => {
2207
+ const txFactory = pgTransaction(connection, options.serializer);
2208
+ return (client, perCallOptions) => txFactory(client, {
2209
+ ...transactionOptions ?? {},
2210
+ ...perCallOptions ?? {}
2211
+ });
2212
+ },
2125
2213
  executor: pgSQLExecutor,
2126
2214
  serializer: options.serializer
2127
2215
  });
2128
2216
  };
2129
2217
  const pgPoolClientConnection = (options) => {
2130
- const { connect, close } = options;
2218
+ const { connect, close, transactionOptions } = options;
2131
2219
  return createConnection({
2132
2220
  driverType: PgDriverType,
2133
2221
  connect,
2134
2222
  close,
2135
- initTransaction: (connection) => pgTransaction(connection, options.serializer),
2223
+ initTransaction: (connection) => {
2224
+ const txFactory = pgTransaction(connection, options.serializer);
2225
+ return (client, perCallOptions) => txFactory(client, {
2226
+ ...transactionOptions ?? {},
2227
+ ...perCallOptions ?? {}
2228
+ });
2229
+ },
2136
2230
  executor: pgSQLExecutor,
2137
2231
  serializer: options.serializer
2138
2232
  });
@@ -2171,7 +2265,7 @@ const setPgTypeParser = (client, options) => {
2171
2265
  //#endregion
2172
2266
  //#region src/storage/postgresql/pg/connections/pool.ts
2173
2267
  const pgNativePool = (options) => {
2174
- const { connectionString, database } = options;
2268
+ const { connectionString, database, transactionOptions } = options;
2175
2269
  const pool = getPgPool({
2176
2270
  connectionString,
2177
2271
  database
@@ -2187,7 +2281,8 @@ const pgNativePool = (options) => {
2187
2281
  return client;
2188
2282
  },
2189
2283
  close: (client) => Promise.resolve(client.release()),
2190
- serializer: options.serializer
2284
+ serializer: options.serializer,
2285
+ ...transactionOptions ? { transactionOptions } : {}
2191
2286
  });
2192
2287
  const open = () => Promise.resolve(getConnection());
2193
2288
  const close = () => endPgPool({
@@ -2202,14 +2297,15 @@ const pgNativePool = (options) => {
2202
2297
  });
2203
2298
  };
2204
2299
  const pgAmbientNativePool = (options) => {
2205
- const { pool } = options;
2300
+ const { pool, transactionOptions } = options;
2206
2301
  return createConnectionPool({
2207
2302
  driverType: PgDriverType,
2208
2303
  getConnection: () => pgConnection({
2209
2304
  type: "PoolClient",
2210
2305
  connect: () => pool.connect(),
2211
2306
  close: (client) => Promise.resolve(client.release()),
2212
- serializer: options.serializer
2307
+ serializer: options.serializer,
2308
+ ...transactionOptions ? { transactionOptions } : {}
2213
2309
  })
2214
2310
  });
2215
2311
  };
@@ -2221,7 +2317,7 @@ const pgAmbientConnectionPool = (options) => {
2221
2317
  });
2222
2318
  };
2223
2319
  const pgClientPool = (options) => {
2224
- const { connectionString, database } = options;
2320
+ const { connectionString, database, transactionOptions } = options;
2225
2321
  return createConnectionPool({
2226
2322
  driverType: PgDriverType,
2227
2323
  getConnection: () => {
@@ -2241,20 +2337,22 @@ const pgClientPool = (options) => {
2241
2337
  type: "Client",
2242
2338
  connect,
2243
2339
  close: (client) => client.end(),
2244
- serializer: options.serializer
2340
+ serializer: options.serializer,
2341
+ ...transactionOptions ? { transactionOptions } : {}
2245
2342
  });
2246
2343
  }
2247
2344
  });
2248
2345
  };
2249
2346
  const pgAmbientClientPool = (options) => {
2250
- const { client } = options;
2347
+ const { client, transactionOptions } = options;
2251
2348
  const getConnection = () => {
2252
2349
  const connect = () => Promise.resolve(client);
2253
2350
  return pgConnection({
2254
2351
  type: "Client",
2255
2352
  connect,
2256
2353
  close: () => Promise.resolve(),
2257
- serializer: options.serializer
2354
+ serializer: options.serializer,
2355
+ ...transactionOptions ? { transactionOptions } : {}
2258
2356
  });
2259
2357
  };
2260
2358
  const open = () => Promise.resolve(getConnection());
@@ -2267,26 +2365,31 @@ const pgAmbientClientPool = (options) => {
2267
2365
  });
2268
2366
  };
2269
2367
  function pgPool(options) {
2270
- const { connectionString, database } = options;
2368
+ const { connectionString, database, transactionOptions } = options;
2271
2369
  const serializer = options.serialization?.serializer ?? JSONSerializer;
2370
+ const txOpts = transactionOptions ? { transactionOptions } : {};
2272
2371
  if ("client" in options && options.client) return pgAmbientClientPool({
2273
2372
  client: options.client,
2274
- serializer
2373
+ serializer,
2374
+ ...txOpts
2275
2375
  });
2276
2376
  if ("connection" in options && options.connection) return pgAmbientConnectionPool({ connection: options.connection });
2277
2377
  if ("pooled" in options && options.pooled === false) return pgClientPool({
2278
2378
  connectionString,
2279
2379
  database,
2280
- serializer
2380
+ serializer,
2381
+ ...txOpts
2281
2382
  });
2282
2383
  if ("pool" in options && options.pool) return pgAmbientNativePool({
2283
2384
  pool: options.pool,
2284
- serializer
2385
+ serializer,
2386
+ ...txOpts
2285
2387
  });
2286
2388
  return pgNativePool({
2287
2389
  connectionString,
2288
2390
  database,
2289
- serializer
2391
+ serializer,
2392
+ ...txOpts
2290
2393
  });
2291
2394
  }
2292
2395
  const pools = /* @__PURE__ */ new Map();