@prisma/client-engine-runtime 7.10.0-dev.8 → 7.10.0-dev.9
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 +112 -53
- package/dist/index.mjs +112 -53
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -2553,6 +2553,14 @@ var InvalidTransactionIsolationLevelError = class extends TransactionManagerErro
|
|
|
2553
2553
|
|
|
2554
2554
|
// src/transaction-manager/transaction-manager.ts
|
|
2555
2555
|
var MAX_CLOSED_TRANSACTIONS = 100;
|
|
2556
|
+
var CANCEL_ROLLBACK_GRACE_MS = 2e3;
|
|
2557
|
+
function trackStartingTransaction() {
|
|
2558
|
+
let markSettled;
|
|
2559
|
+
const settled = new Promise((resolve) => {
|
|
2560
|
+
markSettled = resolve;
|
|
2561
|
+
});
|
|
2562
|
+
return { abortController: new AbortController(), settled, markSettled };
|
|
2563
|
+
}
|
|
2556
2564
|
var debug = (0, import_debug.Debug)("prisma:client:transactionManager");
|
|
2557
2565
|
var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
|
|
2558
2566
|
var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
|
|
@@ -2572,6 +2580,9 @@ var TransactionManager = class {
|
|
|
2572
2580
|
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
2573
2581
|
// Used to provide better error messages than a generic "transaction not found".
|
|
2574
2582
|
closedTransactions = [];
|
|
2583
|
+
// Transactions that are still being started. Tracked separately so that
|
|
2584
|
+
// `cancelAllTransactions` can reach them: they are not in `transactions` yet.
|
|
2585
|
+
#startingTransactions = /* @__PURE__ */ new Set();
|
|
2575
2586
|
driverAdapter;
|
|
2576
2587
|
transactionOptions;
|
|
2577
2588
|
tracingHelper;
|
|
@@ -2635,56 +2646,91 @@ var TransactionManager = class {
|
|
|
2635
2646
|
return { id: existing.id };
|
|
2636
2647
|
});
|
|
2637
2648
|
}
|
|
2638
|
-
const
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2649
|
+
const starting = trackStartingTransaction();
|
|
2650
|
+
const { abortController } = starting;
|
|
2651
|
+
this.#startingTransactions.add(starting);
|
|
2652
|
+
let discarding;
|
|
2653
|
+
try {
|
|
2654
|
+
const transaction = {
|
|
2655
|
+
id: await randomUUID(),
|
|
2656
|
+
status: "waiting",
|
|
2657
|
+
timer: void 0,
|
|
2658
|
+
timeout: options.timeout,
|
|
2659
|
+
startedAt: Date.now(),
|
|
2660
|
+
transaction: void 0,
|
|
2661
|
+
operationQueue: Promise.resolve(),
|
|
2662
|
+
depth: 1,
|
|
2663
|
+
savepoints: [],
|
|
2664
|
+
savepointCounter: 0
|
|
2665
|
+
};
|
|
2666
|
+
if (abortController.signal.aborted) {
|
|
2667
|
+
throw new TransactionStartTimeoutError();
|
|
2668
|
+
}
|
|
2669
|
+
const startTimer = createTimeoutIfDefined(() => abortController.abort(), options.maxWait);
|
|
2670
|
+
startTimer?.unref?.();
|
|
2671
|
+
const startTransactionPromise = this.driverAdapter.startTransaction(options.isolationLevel).catch(rethrowAsUserFacing);
|
|
2672
|
+
transaction.transaction = await Promise.race([
|
|
2673
|
+
startTransactionPromise.finally(() => clearTimeout(startTimer)),
|
|
2674
|
+
once(abortController.signal, "abort").then(() => void 0)
|
|
2675
|
+
]);
|
|
2676
|
+
this.transactions.set(transaction.id, transaction);
|
|
2677
|
+
switch (transaction.status) {
|
|
2678
|
+
case "waiting":
|
|
2679
|
+
if (abortController.signal.aborted) {
|
|
2680
|
+
transaction.transaction = void 0;
|
|
2681
|
+
discarding = this.#discardStartedTransaction(startTransactionPromise);
|
|
2682
|
+
await this.#closeTransaction(transaction, "timed_out");
|
|
2683
|
+
throw new TransactionStartTimeoutError();
|
|
2684
|
+
}
|
|
2685
|
+
transaction.status = "running";
|
|
2686
|
+
transaction.startedAt = Date.now();
|
|
2687
|
+
transaction.timer = this.#startTransactionTimeout(transaction.id, options.timeout);
|
|
2688
|
+
return { id: transaction.id };
|
|
2689
|
+
case "timed_out":
|
|
2690
|
+
case "running":
|
|
2691
|
+
case "committed":
|
|
2692
|
+
case "rolled_back":
|
|
2693
|
+
throw new TransactionInternalConsistencyError(
|
|
2694
|
+
`Transaction in invalid state ${transaction.status} although it just finished startup.`
|
|
2695
|
+
);
|
|
2696
|
+
default:
|
|
2697
|
+
return assertNever(transaction["status"], "Unknown transaction status.");
|
|
2698
|
+
}
|
|
2699
|
+
} finally {
|
|
2700
|
+
this.#startingTransactions.delete(starting);
|
|
2701
|
+
if (discarding) {
|
|
2702
|
+
void discarding.finally(starting.markSettled);
|
|
2703
|
+
} else {
|
|
2704
|
+
starting.markSettled();
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
/**
|
|
2709
|
+
* Rolls back a transaction whose start was abandoned, and releases its connection.
|
|
2710
|
+
*
|
|
2711
|
+
* The `startTransaction` promise may still be running in the background. If it eventually
|
|
2712
|
+
* succeeds, we need to roll back and release the connection to avoid leaking it and
|
|
2713
|
+
* exhausting the connection pool. For adapters that don't use phantom queries (e.g. pg/neon),
|
|
2714
|
+
* `rollback()` only releases the connection without sending SQL, so we send an explicit
|
|
2715
|
+
* ROLLBACK first; otherwise the connection returns to the pool mid-transaction because
|
|
2716
|
+
* `BEGIN` already ran on the wire during startup.
|
|
2717
|
+
*
|
|
2718
|
+
* Errors are only logged: the caller has already reported the failure that led here.
|
|
2719
|
+
*/
|
|
2720
|
+
async #discardStartedTransaction(startTransactionPromise) {
|
|
2721
|
+
try {
|
|
2722
|
+
const tx = await startTransactionPromise;
|
|
2723
|
+
if (tx.options.usePhantomQuery) {
|
|
2724
|
+
await tx.rollback();
|
|
2725
|
+
} else {
|
|
2726
|
+
try {
|
|
2727
|
+
await tx.executeRaw(ROLLBACK_QUERY());
|
|
2728
|
+
} finally {
|
|
2729
|
+
await tx.rollback();
|
|
2675
2730
|
}
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
case "timed_out":
|
|
2680
|
-
case "running":
|
|
2681
|
-
case "committed":
|
|
2682
|
-
case "rolled_back":
|
|
2683
|
-
throw new TransactionInternalConsistencyError(
|
|
2684
|
-
`Transaction in invalid state ${transaction.status} although it just finished startup.`
|
|
2685
|
-
);
|
|
2686
|
-
default:
|
|
2687
|
-
assertNever(transaction["status"], "Unknown transaction status.");
|
|
2731
|
+
}
|
|
2732
|
+
} catch (e) {
|
|
2733
|
+
debug("error in discarded transaction:", e);
|
|
2688
2734
|
}
|
|
2689
2735
|
}
|
|
2690
2736
|
async commitTransaction(transactionId) {
|
|
@@ -2775,16 +2821,21 @@ var TransactionManager = class {
|
|
|
2775
2821
|
return transaction;
|
|
2776
2822
|
}
|
|
2777
2823
|
async cancelAllTransactions() {
|
|
2778
|
-
|
|
2779
|
-
|
|
2824
|
+
const starting = [...this.#startingTransactions];
|
|
2825
|
+
for (const { abortController } of starting) {
|
|
2826
|
+
abortController.abort();
|
|
2827
|
+
}
|
|
2828
|
+
await Promise.allSettled([
|
|
2829
|
+
...[...this.transactions.values()].map(
|
|
2780
2830
|
(tx) => this.#runSerialized(tx, async () => {
|
|
2781
2831
|
const current = this.transactions.get(tx.id);
|
|
2782
2832
|
if (current) {
|
|
2783
2833
|
await this.#closeTransaction(current, "rolled_back");
|
|
2784
2834
|
}
|
|
2785
2835
|
})
|
|
2786
|
-
)
|
|
2787
|
-
|
|
2836
|
+
),
|
|
2837
|
+
...starting.map(({ settled }) => settleWithin(settled, CANCEL_ROLLBACK_GRACE_MS))
|
|
2838
|
+
]);
|
|
2788
2839
|
}
|
|
2789
2840
|
#nextSavepointName(transaction) {
|
|
2790
2841
|
return `prisma_sp_${transaction.savepointCounter++}`;
|
|
@@ -2937,6 +2988,14 @@ var TransactionManager = class {
|
|
|
2937
2988
|
function createTimeoutIfDefined(cb, ms) {
|
|
2938
2989
|
return ms !== void 0 ? setTimeout(cb, ms) : void 0;
|
|
2939
2990
|
}
|
|
2991
|
+
function settleWithin(promise, timeout) {
|
|
2992
|
+
let timer;
|
|
2993
|
+
const deadline = new Promise((resolve) => {
|
|
2994
|
+
timer = setTimeout(resolve, timeout);
|
|
2995
|
+
timer?.unref?.();
|
|
2996
|
+
});
|
|
2997
|
+
return Promise.race([promise, deadline]).finally(() => clearTimeout(timer));
|
|
2998
|
+
}
|
|
2940
2999
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2941
3000
|
0 && (module.exports = {
|
|
2942
3001
|
DataMapperError,
|
package/dist/index.mjs
CHANGED
|
@@ -2500,6 +2500,14 @@ var InvalidTransactionIsolationLevelError = class extends TransactionManagerErro
|
|
|
2500
2500
|
|
|
2501
2501
|
// src/transaction-manager/transaction-manager.ts
|
|
2502
2502
|
var MAX_CLOSED_TRANSACTIONS = 100;
|
|
2503
|
+
var CANCEL_ROLLBACK_GRACE_MS = 2e3;
|
|
2504
|
+
function trackStartingTransaction() {
|
|
2505
|
+
let markSettled;
|
|
2506
|
+
const settled = new Promise((resolve) => {
|
|
2507
|
+
markSettled = resolve;
|
|
2508
|
+
});
|
|
2509
|
+
return { abortController: new AbortController(), settled, markSettled };
|
|
2510
|
+
}
|
|
2503
2511
|
var debug = Debug("prisma:client:transactionManager");
|
|
2504
2512
|
var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
|
|
2505
2513
|
var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
|
|
@@ -2519,6 +2527,9 @@ var TransactionManager = class {
|
|
|
2519
2527
|
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
2520
2528
|
// Used to provide better error messages than a generic "transaction not found".
|
|
2521
2529
|
closedTransactions = [];
|
|
2530
|
+
// Transactions that are still being started. Tracked separately so that
|
|
2531
|
+
// `cancelAllTransactions` can reach them: they are not in `transactions` yet.
|
|
2532
|
+
#startingTransactions = /* @__PURE__ */ new Set();
|
|
2522
2533
|
driverAdapter;
|
|
2523
2534
|
transactionOptions;
|
|
2524
2535
|
tracingHelper;
|
|
@@ -2582,56 +2593,91 @@ var TransactionManager = class {
|
|
|
2582
2593
|
return { id: existing.id };
|
|
2583
2594
|
});
|
|
2584
2595
|
}
|
|
2585
|
-
const
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2596
|
+
const starting = trackStartingTransaction();
|
|
2597
|
+
const { abortController } = starting;
|
|
2598
|
+
this.#startingTransactions.add(starting);
|
|
2599
|
+
let discarding;
|
|
2600
|
+
try {
|
|
2601
|
+
const transaction = {
|
|
2602
|
+
id: await randomUUID(),
|
|
2603
|
+
status: "waiting",
|
|
2604
|
+
timer: void 0,
|
|
2605
|
+
timeout: options.timeout,
|
|
2606
|
+
startedAt: Date.now(),
|
|
2607
|
+
transaction: void 0,
|
|
2608
|
+
operationQueue: Promise.resolve(),
|
|
2609
|
+
depth: 1,
|
|
2610
|
+
savepoints: [],
|
|
2611
|
+
savepointCounter: 0
|
|
2612
|
+
};
|
|
2613
|
+
if (abortController.signal.aborted) {
|
|
2614
|
+
throw new TransactionStartTimeoutError();
|
|
2615
|
+
}
|
|
2616
|
+
const startTimer = createTimeoutIfDefined(() => abortController.abort(), options.maxWait);
|
|
2617
|
+
startTimer?.unref?.();
|
|
2618
|
+
const startTransactionPromise = this.driverAdapter.startTransaction(options.isolationLevel).catch(rethrowAsUserFacing);
|
|
2619
|
+
transaction.transaction = await Promise.race([
|
|
2620
|
+
startTransactionPromise.finally(() => clearTimeout(startTimer)),
|
|
2621
|
+
once(abortController.signal, "abort").then(() => void 0)
|
|
2622
|
+
]);
|
|
2623
|
+
this.transactions.set(transaction.id, transaction);
|
|
2624
|
+
switch (transaction.status) {
|
|
2625
|
+
case "waiting":
|
|
2626
|
+
if (abortController.signal.aborted) {
|
|
2627
|
+
transaction.transaction = void 0;
|
|
2628
|
+
discarding = this.#discardStartedTransaction(startTransactionPromise);
|
|
2629
|
+
await this.#closeTransaction(transaction, "timed_out");
|
|
2630
|
+
throw new TransactionStartTimeoutError();
|
|
2631
|
+
}
|
|
2632
|
+
transaction.status = "running";
|
|
2633
|
+
transaction.startedAt = Date.now();
|
|
2634
|
+
transaction.timer = this.#startTransactionTimeout(transaction.id, options.timeout);
|
|
2635
|
+
return { id: transaction.id };
|
|
2636
|
+
case "timed_out":
|
|
2637
|
+
case "running":
|
|
2638
|
+
case "committed":
|
|
2639
|
+
case "rolled_back":
|
|
2640
|
+
throw new TransactionInternalConsistencyError(
|
|
2641
|
+
`Transaction in invalid state ${transaction.status} although it just finished startup.`
|
|
2642
|
+
);
|
|
2643
|
+
default:
|
|
2644
|
+
return assertNever(transaction["status"], "Unknown transaction status.");
|
|
2645
|
+
}
|
|
2646
|
+
} finally {
|
|
2647
|
+
this.#startingTransactions.delete(starting);
|
|
2648
|
+
if (discarding) {
|
|
2649
|
+
void discarding.finally(starting.markSettled);
|
|
2650
|
+
} else {
|
|
2651
|
+
starting.markSettled();
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
/**
|
|
2656
|
+
* Rolls back a transaction whose start was abandoned, and releases its connection.
|
|
2657
|
+
*
|
|
2658
|
+
* The `startTransaction` promise may still be running in the background. If it eventually
|
|
2659
|
+
* succeeds, we need to roll back and release the connection to avoid leaking it and
|
|
2660
|
+
* exhausting the connection pool. For adapters that don't use phantom queries (e.g. pg/neon),
|
|
2661
|
+
* `rollback()` only releases the connection without sending SQL, so we send an explicit
|
|
2662
|
+
* ROLLBACK first; otherwise the connection returns to the pool mid-transaction because
|
|
2663
|
+
* `BEGIN` already ran on the wire during startup.
|
|
2664
|
+
*
|
|
2665
|
+
* Errors are only logged: the caller has already reported the failure that led here.
|
|
2666
|
+
*/
|
|
2667
|
+
async #discardStartedTransaction(startTransactionPromise) {
|
|
2668
|
+
try {
|
|
2669
|
+
const tx = await startTransactionPromise;
|
|
2670
|
+
if (tx.options.usePhantomQuery) {
|
|
2671
|
+
await tx.rollback();
|
|
2672
|
+
} else {
|
|
2673
|
+
try {
|
|
2674
|
+
await tx.executeRaw(ROLLBACK_QUERY());
|
|
2675
|
+
} finally {
|
|
2676
|
+
await tx.rollback();
|
|
2622
2677
|
}
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
case "timed_out":
|
|
2627
|
-
case "running":
|
|
2628
|
-
case "committed":
|
|
2629
|
-
case "rolled_back":
|
|
2630
|
-
throw new TransactionInternalConsistencyError(
|
|
2631
|
-
`Transaction in invalid state ${transaction.status} although it just finished startup.`
|
|
2632
|
-
);
|
|
2633
|
-
default:
|
|
2634
|
-
assertNever(transaction["status"], "Unknown transaction status.");
|
|
2678
|
+
}
|
|
2679
|
+
} catch (e) {
|
|
2680
|
+
debug("error in discarded transaction:", e);
|
|
2635
2681
|
}
|
|
2636
2682
|
}
|
|
2637
2683
|
async commitTransaction(transactionId) {
|
|
@@ -2722,16 +2768,21 @@ var TransactionManager = class {
|
|
|
2722
2768
|
return transaction;
|
|
2723
2769
|
}
|
|
2724
2770
|
async cancelAllTransactions() {
|
|
2725
|
-
|
|
2726
|
-
|
|
2771
|
+
const starting = [...this.#startingTransactions];
|
|
2772
|
+
for (const { abortController } of starting) {
|
|
2773
|
+
abortController.abort();
|
|
2774
|
+
}
|
|
2775
|
+
await Promise.allSettled([
|
|
2776
|
+
...[...this.transactions.values()].map(
|
|
2727
2777
|
(tx) => this.#runSerialized(tx, async () => {
|
|
2728
2778
|
const current = this.transactions.get(tx.id);
|
|
2729
2779
|
if (current) {
|
|
2730
2780
|
await this.#closeTransaction(current, "rolled_back");
|
|
2731
2781
|
}
|
|
2732
2782
|
})
|
|
2733
|
-
)
|
|
2734
|
-
|
|
2783
|
+
),
|
|
2784
|
+
...starting.map(({ settled }) => settleWithin(settled, CANCEL_ROLLBACK_GRACE_MS))
|
|
2785
|
+
]);
|
|
2735
2786
|
}
|
|
2736
2787
|
#nextSavepointName(transaction) {
|
|
2737
2788
|
return `prisma_sp_${transaction.savepointCounter++}`;
|
|
@@ -2884,6 +2935,14 @@ var TransactionManager = class {
|
|
|
2884
2935
|
function createTimeoutIfDefined(cb, ms) {
|
|
2885
2936
|
return ms !== void 0 ? setTimeout(cb, ms) : void 0;
|
|
2886
2937
|
}
|
|
2938
|
+
function settleWithin(promise, timeout) {
|
|
2939
|
+
let timer;
|
|
2940
|
+
const deadline = new Promise((resolve) => {
|
|
2941
|
+
timer = setTimeout(resolve, timeout);
|
|
2942
|
+
timer?.unref?.();
|
|
2943
|
+
});
|
|
2944
|
+
return Promise.race([promise, deadline]).finally(() => clearTimeout(timer));
|
|
2945
|
+
}
|
|
2887
2946
|
export {
|
|
2888
2947
|
DataMapperError,
|
|
2889
2948
|
QueryInterpreter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "7.10.0-dev.
|
|
3
|
+
"version": "7.10.0-dev.9",
|
|
4
4
|
"description": "This package is intended for Prisma's internal use",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"nanoid": "5.1.5",
|
|
32
32
|
"ulid": "3.0.0",
|
|
33
33
|
"uuid": "14.0.0",
|
|
34
|
-
"@prisma/
|
|
35
|
-
"@prisma/
|
|
36
|
-
"@prisma/
|
|
37
|
-
"@prisma/
|
|
38
|
-
"@prisma/
|
|
39
|
-
"@prisma/json-protocol": "7.10.0-dev.
|
|
34
|
+
"@prisma/driver-adapter-utils": "7.10.0-dev.9",
|
|
35
|
+
"@prisma/sqlcommenter": "7.10.0-dev.9",
|
|
36
|
+
"@prisma/param-graph": "7.10.0-dev.9",
|
|
37
|
+
"@prisma/client-runtime-utils": "7.10.0-dev.9",
|
|
38
|
+
"@prisma/debug": "7.10.0-dev.9",
|
|
39
|
+
"@prisma/json-protocol": "7.10.0-dev.9"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@codspeed/benchmark.js-plugin": "4.0.0",
|
|
43
43
|
"@types/benchmark": "2.1.5",
|
|
44
44
|
"@types/node": "~20.19.24",
|
|
45
45
|
"benchmark": "2.1.4",
|
|
46
|
-
"@prisma/get-dmmf": "7.10.0-dev.
|
|
47
|
-
"@prisma/param-graph-builder": "7.10.0-dev.
|
|
46
|
+
"@prisma/get-dmmf": "7.10.0-dev.9",
|
|
47
|
+
"@prisma/param-graph-builder": "7.10.0-dev.9"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"dist"
|