@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.js CHANGED
@@ -346,6 +346,65 @@ const executeInNewConnection = async (handle, options) => {
346
346
 
347
347
  //#endregion
348
348
  //#region src/core/connections/transaction.ts
349
+ const transactionNestingCounter = () => {
350
+ let transactionLevel = 0;
351
+ return {
352
+ reset: () => {
353
+ transactionLevel = 0;
354
+ },
355
+ increment: () => {
356
+ transactionLevel++;
357
+ },
358
+ decrement: () => {
359
+ transactionLevel--;
360
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
361
+ },
362
+ get level() {
363
+ return transactionLevel;
364
+ }
365
+ };
366
+ };
367
+ const databaseTransaction = (backend, options) => {
368
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
369
+ const useSavepoints = options?.useSavepoints ?? false;
370
+ const counter = transactionNestingCounter();
371
+ let hasBegun = false;
372
+ return {
373
+ begin: async () => {
374
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
375
+ if (allowNestedTransactions) {
376
+ if (counter.level >= 1) {
377
+ counter.increment();
378
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
379
+ return;
380
+ }
381
+ counter.increment();
382
+ }
383
+ hasBegun = true;
384
+ await backend.begin();
385
+ },
386
+ commit: async () => {
387
+ if (allowNestedTransactions && counter.level > 1) {
388
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
389
+ counter.decrement();
390
+ return;
391
+ }
392
+ if (allowNestedTransactions) counter.reset();
393
+ hasBegun = false;
394
+ await backend.commit();
395
+ },
396
+ rollback: async (error) => {
397
+ if (allowNestedTransactions && counter.level > 1) {
398
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
399
+ counter.decrement();
400
+ return;
401
+ }
402
+ if (allowNestedTransactions) counter.reset();
403
+ hasBegun = false;
404
+ await backend.rollback(error);
405
+ }
406
+ };
407
+ };
349
408
  const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
350
409
  success: true,
351
410
  result: transactionResult
@@ -2052,57 +2111,92 @@ async function batchCommand(client, sqls, serializer, options) {
2052
2111
 
2053
2112
  //#endregion
2054
2113
  //#region src/storage/postgresql/pg/connections/transaction.ts
2055
- const pgTransaction = (connection, serializer) => (getClient, options) => ({
2056
- connection: connection(),
2057
- driverType: PgDriverType,
2058
- begin: async () => {
2059
- const client = await getClient;
2060
- const parts = ["BEGIN"];
2061
- if (options?.isolationLevel) parts.push(`ISOLATION LEVEL ${options.isolationLevel}`);
2062
- if (options?.readonly) parts.push("READ ONLY");
2063
- await client.query(parts.join(" "));
2064
- },
2065
- commit: async () => {
2066
- const client = await getClient;
2067
- try {
2068
- await client.query("COMMIT");
2069
- } finally {
2070
- if (options?.close) await options?.close(client);
2114
+ const pgTransaction = (connection, serializer) => (getClient, options) => {
2115
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
2116
+ const tx = databaseTransaction({
2117
+ begin: async () => {
2118
+ const client = await getClient;
2119
+ const parts = ["BEGIN"];
2120
+ if (options?.isolationLevel) parts.push(`ISOLATION LEVEL ${options.isolationLevel}`);
2121
+ if (options?.readonly) parts.push("READ ONLY");
2122
+ await client.query(parts.join(" "));
2123
+ },
2124
+ commit: async () => {
2125
+ const client = await getClient;
2126
+ try {
2127
+ await client.query("COMMIT");
2128
+ } finally {
2129
+ if (options?.close) await options.close(client);
2130
+ }
2131
+ },
2132
+ rollback: async (error) => {
2133
+ const client = await getClient;
2134
+ try {
2135
+ await client.query("ROLLBACK");
2136
+ } finally {
2137
+ if (options?.close) await options.close(client, error);
2138
+ }
2139
+ },
2140
+ savepoint: async (level) => {
2141
+ await (await getClient).query(`SAVEPOINT pg_savepoint_${level}`);
2142
+ },
2143
+ releaseSavepoint: async (level) => {
2144
+ await (await getClient).query(`RELEASE SAVEPOINT pg_savepoint_${level}`);
2145
+ },
2146
+ rollbackToSavepoint: async (level) => {
2147
+ await (await getClient).query(`ROLLBACK TO SAVEPOINT pg_savepoint_${level}`);
2071
2148
  }
2072
- },
2073
- rollback: async (error) => {
2074
- const client = await getClient;
2075
- try {
2076
- await client.query("ROLLBACK");
2077
- } finally {
2078
- if (options?.close) await options?.close(client, error);
2149
+ }, {
2150
+ allowNestedTransactions,
2151
+ useSavepoints: options?.useSavepoints ?? false
2152
+ });
2153
+ return {
2154
+ connection: connection(),
2155
+ driverType: PgDriverType,
2156
+ begin: tx.begin,
2157
+ commit: tx.commit,
2158
+ rollback: tx.rollback,
2159
+ execute: sqlExecutor(pgSQLExecutor({ serializer }), { connect: () => getClient }),
2160
+ _transactionOptions: {
2161
+ ...options ?? {},
2162
+ allowNestedTransactions
2079
2163
  }
2080
- },
2081
- execute: sqlExecutor(pgSQLExecutor({ serializer }), { connect: () => getClient }),
2082
- _transactionOptions: options ?? {}
2083
- });
2164
+ };
2165
+ };
2084
2166
 
2085
2167
  //#endregion
2086
2168
  //#region src/storage/postgresql/pg/connections/connection.ts
2087
2169
  const PgDriverType = "PostgreSQL:pg";
2088
2170
  const pgClientConnection = (options) => {
2089
- const { connect, close } = options;
2171
+ const { connect, close, transactionOptions } = options;
2090
2172
  return createConnection({
2091
2173
  driverType: PgDriverType,
2092
2174
  connect,
2093
2175
  close,
2094
- initTransaction: (connection) => pgTransaction(connection, options.serializer),
2176
+ initTransaction: (connection) => {
2177
+ const txFactory = pgTransaction(connection, options.serializer);
2178
+ return (client, perCallOptions) => txFactory(client, {
2179
+ ...transactionOptions ?? {},
2180
+ ...perCallOptions ?? {}
2181
+ });
2182
+ },
2095
2183
  executor: pgSQLExecutor,
2096
2184
  serializer: options.serializer
2097
2185
  });
2098
2186
  };
2099
2187
  const pgPoolClientConnection = (options) => {
2100
- const { connect, close } = options;
2188
+ const { connect, close, transactionOptions } = options;
2101
2189
  return createConnection({
2102
2190
  driverType: PgDriverType,
2103
2191
  connect,
2104
2192
  close,
2105
- initTransaction: (connection) => pgTransaction(connection, options.serializer),
2193
+ initTransaction: (connection) => {
2194
+ const txFactory = pgTransaction(connection, options.serializer);
2195
+ return (client, perCallOptions) => txFactory(client, {
2196
+ ...transactionOptions ?? {},
2197
+ ...perCallOptions ?? {}
2198
+ });
2199
+ },
2106
2200
  executor: pgSQLExecutor,
2107
2201
  serializer: options.serializer
2108
2202
  });
@@ -2141,7 +2235,7 @@ const setPgTypeParser = (client, options) => {
2141
2235
  //#endregion
2142
2236
  //#region src/storage/postgresql/pg/connections/pool.ts
2143
2237
  const pgNativePool = (options) => {
2144
- const { connectionString, database } = options;
2238
+ const { connectionString, database, transactionOptions } = options;
2145
2239
  const pool = getPgPool({
2146
2240
  connectionString,
2147
2241
  database
@@ -2157,7 +2251,8 @@ const pgNativePool = (options) => {
2157
2251
  return client;
2158
2252
  },
2159
2253
  close: (client) => Promise.resolve(client.release()),
2160
- serializer: options.serializer
2254
+ serializer: options.serializer,
2255
+ ...transactionOptions ? { transactionOptions } : {}
2161
2256
  });
2162
2257
  const open = () => Promise.resolve(getConnection());
2163
2258
  const close = () => endPgPool({
@@ -2172,14 +2267,15 @@ const pgNativePool = (options) => {
2172
2267
  });
2173
2268
  };
2174
2269
  const pgAmbientNativePool = (options) => {
2175
- const { pool } = options;
2270
+ const { pool, transactionOptions } = options;
2176
2271
  return createConnectionPool({
2177
2272
  driverType: PgDriverType,
2178
2273
  getConnection: () => pgConnection({
2179
2274
  type: "PoolClient",
2180
2275
  connect: () => pool.connect(),
2181
2276
  close: (client) => Promise.resolve(client.release()),
2182
- serializer: options.serializer
2277
+ serializer: options.serializer,
2278
+ ...transactionOptions ? { transactionOptions } : {}
2183
2279
  })
2184
2280
  });
2185
2281
  };
@@ -2191,7 +2287,7 @@ const pgAmbientConnectionPool = (options) => {
2191
2287
  });
2192
2288
  };
2193
2289
  const pgClientPool = (options) => {
2194
- const { connectionString, database } = options;
2290
+ const { connectionString, database, transactionOptions } = options;
2195
2291
  return createConnectionPool({
2196
2292
  driverType: PgDriverType,
2197
2293
  getConnection: () => {
@@ -2211,20 +2307,22 @@ const pgClientPool = (options) => {
2211
2307
  type: "Client",
2212
2308
  connect,
2213
2309
  close: (client) => client.end(),
2214
- serializer: options.serializer
2310
+ serializer: options.serializer,
2311
+ ...transactionOptions ? { transactionOptions } : {}
2215
2312
  });
2216
2313
  }
2217
2314
  });
2218
2315
  };
2219
2316
  const pgAmbientClientPool = (options) => {
2220
- const { client } = options;
2317
+ const { client, transactionOptions } = options;
2221
2318
  const getConnection = () => {
2222
2319
  const connect = () => Promise.resolve(client);
2223
2320
  return pgConnection({
2224
2321
  type: "Client",
2225
2322
  connect,
2226
2323
  close: () => Promise.resolve(),
2227
- serializer: options.serializer
2324
+ serializer: options.serializer,
2325
+ ...transactionOptions ? { transactionOptions } : {}
2228
2326
  });
2229
2327
  };
2230
2328
  const open = () => Promise.resolve(getConnection());
@@ -2237,26 +2335,31 @@ const pgAmbientClientPool = (options) => {
2237
2335
  });
2238
2336
  };
2239
2337
  function pgPool(options) {
2240
- const { connectionString, database } = options;
2338
+ const { connectionString, database, transactionOptions } = options;
2241
2339
  const serializer = options.serialization?.serializer ?? JSONSerializer;
2340
+ const txOpts = transactionOptions ? { transactionOptions } : {};
2242
2341
  if ("client" in options && options.client) return pgAmbientClientPool({
2243
2342
  client: options.client,
2244
- serializer
2343
+ serializer,
2344
+ ...txOpts
2245
2345
  });
2246
2346
  if ("connection" in options && options.connection) return pgAmbientConnectionPool({ connection: options.connection });
2247
2347
  if ("pooled" in options && options.pooled === false) return pgClientPool({
2248
2348
  connectionString,
2249
2349
  database,
2250
- serializer
2350
+ serializer,
2351
+ ...txOpts
2251
2352
  });
2252
2353
  if ("pool" in options && options.pool) return pgAmbientNativePool({
2253
2354
  pool: options.pool,
2254
- serializer
2355
+ serializer,
2356
+ ...txOpts
2255
2357
  });
2256
2358
  return pgNativePool({
2257
2359
  connectionString,
2258
2360
  database,
2259
- serializer
2361
+ serializer,
2362
+ ...txOpts
2260
2363
  });
2261
2364
  }
2262
2365
  const pools = /* @__PURE__ */ new Map();