@aventara/prisma7-adapter 1.0.0-rc.13 → 1.0.0-rc.14
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @aventara/prisma7-adapter
|
|
2
2
|
|
|
3
|
+
## 1.0.0-rc.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 28688e4: On SQLite (`@prisma/adapter-better-sqlite3`), a plain operation or `ctx.$sql` that gives up waiting for the connection another request's transaction holds still answers `A3002`, and its diagnostic now says so: how many milliseconds it waited, the `maxWait` that ran out (the adapter's `transactionOptions.maxWait`, or else the PrismaClient's, 2000 ms unless set on the client), and that it never ran. A transaction that fails to open for another reason, such as an unsupported isolation level, keeps its usual diagnostic. Before, the diagnostic said the call's transaction "was no longer open", which named the wrong cause. Raise the adapter's `transactionOptions.maxWait`, or keep the transaction that holds the connection shorter.
|
|
8
|
+
- Updated dependencies [1c5eaa3]
|
|
9
|
+
- @aventara/core@1.0.0-rc.14
|
|
10
|
+
|
|
3
11
|
## 1.0.0-rc.13
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -101,7 +101,8 @@ connection without waiting, so a plain call made meanwhile would run inside the
|
|
|
101
101
|
see its uncommitted rows and roll back with it. With that driver, an operation that is not part of a
|
|
102
102
|
transaction, and a `ctx.$sql` that is not, each run in a `$transaction` of their own that holds only that
|
|
103
103
|
call. They wait on the driver's own lock, so operations and transactions queue for the connection and run
|
|
104
|
-
one at a time. `transactionOptions` apply to the wait: past `maxWait` the operation answers `A3002`,
|
|
104
|
+
one at a time. `transactionOptions` apply to the wait: past `maxWait` the operation answers `A3002`, its
|
|
105
|
+
diagnostic says how long it waited for the connection another request's transaction held, and
|
|
105
106
|
`timeout` limits a single plain operation too. `@prisma/adapter-pg` checks a connection of its own out of
|
|
106
107
|
the pool for each transaction, and D1 runs none, so both stay as they were. Calls made on the Prisma client
|
|
107
108
|
directly, outside Aventara, are not covered.
|
|
@@ -66,6 +66,21 @@ export declare function classifyPrismaError(error: unknown, operation: Pick<AvOp
|
|
|
66
66
|
export declare function classifyPrismaStatementError(error: unknown): PrismaErrorClassification;
|
|
67
67
|
/** The deliberate failure an `outcome` classification stands for. */
|
|
68
68
|
export declare function prismaOutcomeFailure(code: AvOperationErrorCode): AvError;
|
|
69
|
+
/**
|
|
70
|
+
* Whether a failure to open a transaction has the structure of the `maxWait`
|
|
71
|
+
* acquisition timeout: `P2028` with an empty `meta`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function isPrismaAcquisitionTimeout(error: unknown): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* `A3002` for a plain call on a one-connection driver that gave up waiting for
|
|
76
|
+
* the connection another request's transaction held: its own transaction never
|
|
77
|
+
* opened, so `OUTCOME_MESSAGES`' "no longer open" text would name the wrong
|
|
78
|
+
* cause. Diagnostics only, like every `A3xxx` text here.
|
|
79
|
+
*/
|
|
80
|
+
export declare function prismaConnectionWaitFailure(facts: {
|
|
81
|
+
readonly waitedMs: number;
|
|
82
|
+
readonly maxWait: number | undefined;
|
|
83
|
+
}): AvError;
|
|
69
84
|
/** The `A2004` a value the database refused answers: one issue at the arguments (or the value in them) saying what was refused. */
|
|
70
85
|
export declare function prismaValueFailure(refusal: PrismaValueRefusal, path?: PrismaArgumentPath): AvError;
|
|
71
86
|
/** The `A2004` a nested write that writes its relation back answers: `V1012` at `path`. */
|
|
@@ -127,6 +127,18 @@ export function prismaOutcomeFailure(code) {
|
|
|
127
127
|
message: OUTCOME_MESSAGES[code] ?? "The operation could not be completed.",
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
|
+
export function isPrismaAcquisitionTimeout(error) {
|
|
131
|
+
const facts = readPrismaError(error);
|
|
132
|
+
return facts.code === "P2028" && facts.metaKeys.length === 0;
|
|
133
|
+
}
|
|
134
|
+
export function prismaConnectionWaitFailure(facts) {
|
|
135
|
+
const limit = facts.maxWait === undefined
|
|
136
|
+
? "the PrismaClient's maxWait (2000 ms unless set on the client)"
|
|
137
|
+
: `the adapter's maxWait (${facts.maxWait} ms)`;
|
|
138
|
+
return new AvError("A3002", {
|
|
139
|
+
message: `This call waited ${Math.round(facts.waitedMs)} ms for the SQLite connection, which another request's transaction held, and gave up when ${limit} ran out: it never ran and wrote nothing. Raise the adapter's transactionOptions.maxWait, or keep the transaction that holds the connection shorter.`,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
130
142
|
export function prismaValueFailure(refusal, path = []) {
|
|
131
143
|
const { code, message } = DATABASE_REFUSALS[refusal];
|
|
132
144
|
return new AvError("A2004", {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { emitAdapterWarning } from "../adapter-warning.emitter.js";
|
|
2
|
-
import { classifyPrismaStatementError, prismaOutcomeFailure, } from "../errors/error.normalizer.js";
|
|
2
|
+
import { classifyPrismaStatementError, isPrismaAcquisitionTimeout, prismaConnectionWaitFailure, prismaOutcomeFailure, } from "../errors/error.normalizer.js";
|
|
3
3
|
const TRANSACTION_JOINED_WARNING = "AVENTARA_PRISMA_SQLITE_TRANSACTION_JOINED";
|
|
4
4
|
const warnedJoins = new Set();
|
|
5
5
|
function warnJoined(call) {
|
|
@@ -40,7 +40,9 @@ export function createSharedConnectionRouter(dependencies) {
|
|
|
40
40
|
return work(joined.client);
|
|
41
41
|
}
|
|
42
42
|
let thrownByWork = false;
|
|
43
|
+
let started = false;
|
|
43
44
|
const run = async (transactional) => {
|
|
45
|
+
started = true;
|
|
44
46
|
try {
|
|
45
47
|
return await within(transactional, () => work(transactional));
|
|
46
48
|
}
|
|
@@ -50,6 +52,7 @@ export function createSharedConnectionRouter(dependencies) {
|
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
54
|
const options = dependencies.transactionOptions;
|
|
55
|
+
const waitedFrom = performance.now();
|
|
53
56
|
try {
|
|
54
57
|
return await (options === undefined
|
|
55
58
|
? dependencies.client.$transaction(run)
|
|
@@ -61,7 +64,14 @@ export function createSharedConnectionRouter(dependencies) {
|
|
|
61
64
|
}
|
|
62
65
|
const classification = classifyPrismaStatementError(error);
|
|
63
66
|
if (classification.kind === "outcome") {
|
|
64
|
-
|
|
67
|
+
const waitedMs = performance.now() - waitedFrom;
|
|
68
|
+
const maxWait = options?.maxWait;
|
|
69
|
+
const waitedOut = !started &&
|
|
70
|
+
isPrismaAcquisitionTimeout(error) &&
|
|
71
|
+
(maxWait === undefined || waitedMs + 1 >= maxWait);
|
|
72
|
+
throw waitedOut
|
|
73
|
+
? prismaConnectionWaitFailure({ waitedMs, maxWait })
|
|
74
|
+
: prismaOutcomeFailure(classification.code);
|
|
65
75
|
}
|
|
66
76
|
throw error;
|
|
67
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aventara/prisma7-adapter",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.14",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "The Prisma 7 adapter for Aventara.",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"CHANGELOG.md"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@aventara/core": "1.0.0-rc.
|
|
33
|
+
"@aventara/core": "1.0.0-rc.14"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@prisma/adapter-better-sqlite3": "^7.10.1",
|