@prisma/client-engine-runtime 6.7.0-dev.2 → 6.7.0-dev.20
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/QueryPlan.d.ts +2 -0
- package/dist/UserFacingError.d.ts +16 -0
- package/dist/index.d.mts +39 -2
- package/dist/index.d.ts +39 -2
- package/dist/index.js +302 -77
- package/dist/index.mjs +299 -76
- package/dist/interpreter/QueryInterpreter.d.ts +3 -1
- package/dist/tracing.d.ts +11 -0
- package/dist/transactionManager/TransactionManager.d.ts +5 -1
- package/dist/transactionManager/TransactionManagerErrors.d.ts +1 -7
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -33,11 +33,183 @@ __export(index_exports, {
|
|
|
33
33
|
QueryInterpreter: () => QueryInterpreter,
|
|
34
34
|
TransactionManager: () => TransactionManager,
|
|
35
35
|
TransactionManagerError: () => TransactionManagerError,
|
|
36
|
+
UserFacingError: () => UserFacingError,
|
|
36
37
|
isPrismaValueGenerator: () => isPrismaValueGenerator,
|
|
37
|
-
isPrismaValuePlaceholder: () => isPrismaValuePlaceholder
|
|
38
|
+
isPrismaValuePlaceholder: () => isPrismaValuePlaceholder,
|
|
39
|
+
noopTracingHelper: () => noopTracingHelper
|
|
38
40
|
});
|
|
39
41
|
module.exports = __toCommonJS(index_exports);
|
|
40
42
|
|
|
43
|
+
// src/interpreter/QueryInterpreter.ts
|
|
44
|
+
var import_api = require("@opentelemetry/api");
|
|
45
|
+
|
|
46
|
+
// src/utils.ts
|
|
47
|
+
function assertNever(_, message) {
|
|
48
|
+
throw new Error(message);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/tracing.ts
|
|
52
|
+
var noopTracingHelper = {
|
|
53
|
+
runInChildSpan(_, callback) {
|
|
54
|
+
return callback();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
function providerToOtelSystem(provider) {
|
|
58
|
+
switch (provider) {
|
|
59
|
+
case "postgres":
|
|
60
|
+
return "postgresql";
|
|
61
|
+
case "mysql":
|
|
62
|
+
return "mysql";
|
|
63
|
+
case "sqlite":
|
|
64
|
+
return "sqlite";
|
|
65
|
+
default:
|
|
66
|
+
assertNever(provider, `Unknown provider: ${provider}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/UserFacingError.ts
|
|
71
|
+
var import_driver_adapter_utils = require("@prisma/driver-adapter-utils");
|
|
72
|
+
var UserFacingError = class extends Error {
|
|
73
|
+
name = "UserFacingError";
|
|
74
|
+
code;
|
|
75
|
+
meta;
|
|
76
|
+
constructor(message, code, meta) {
|
|
77
|
+
super(message);
|
|
78
|
+
this.code = code;
|
|
79
|
+
this.meta = meta;
|
|
80
|
+
}
|
|
81
|
+
toQueryResponseErrorObject() {
|
|
82
|
+
return {
|
|
83
|
+
error: this.message,
|
|
84
|
+
user_facing_error: {
|
|
85
|
+
is_panic: false,
|
|
86
|
+
message: this.message,
|
|
87
|
+
meta: this.meta,
|
|
88
|
+
error_code: this.code
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
function rethrowAsUserFacing(error) {
|
|
94
|
+
if (!(0, import_driver_adapter_utils.isDriverAdapterError)(error)) {
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
const code = getErrorCode(error);
|
|
98
|
+
const message = renderErrorMessage(error);
|
|
99
|
+
if (!code || !message) {
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
throw new UserFacingError(message, code, error);
|
|
103
|
+
}
|
|
104
|
+
function getErrorCode(err) {
|
|
105
|
+
switch (err.cause.kind) {
|
|
106
|
+
case "AuthenticationFailed":
|
|
107
|
+
return "P1000";
|
|
108
|
+
case "DatabaseDoesNotExist":
|
|
109
|
+
return "P1003";
|
|
110
|
+
case "SocketTimeout":
|
|
111
|
+
return "P1008";
|
|
112
|
+
case "DatabaseAlreadyExists":
|
|
113
|
+
return "P1009";
|
|
114
|
+
case "DatabaseAccessDenied":
|
|
115
|
+
return "P1010";
|
|
116
|
+
case "LengthMismatch":
|
|
117
|
+
return "P2000";
|
|
118
|
+
case "UniqueConstraintViolation":
|
|
119
|
+
return "P2002";
|
|
120
|
+
case "ForeignKeyConstraintViolation":
|
|
121
|
+
return "P2003";
|
|
122
|
+
case "UnsupportedNativeDataType":
|
|
123
|
+
return "P2010";
|
|
124
|
+
case "NullConstraintViolation":
|
|
125
|
+
return "P2011";
|
|
126
|
+
case "TableDoesNotExist":
|
|
127
|
+
return "P2021";
|
|
128
|
+
case "ColumnNotFound":
|
|
129
|
+
return "P2022";
|
|
130
|
+
case "InvalidIsolationLevel":
|
|
131
|
+
return "P2023";
|
|
132
|
+
case "TransactionWriteConflict":
|
|
133
|
+
return "P2034";
|
|
134
|
+
case "GenericJs":
|
|
135
|
+
return "P2036";
|
|
136
|
+
case "TooManyConnections":
|
|
137
|
+
return "P2037";
|
|
138
|
+
case "postgres":
|
|
139
|
+
case "sqlite":
|
|
140
|
+
case "mysql":
|
|
141
|
+
return;
|
|
142
|
+
default:
|
|
143
|
+
assertNever(err.cause, `Unknown error: ${err.cause}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function renderErrorMessage(err) {
|
|
147
|
+
switch (err.cause.kind) {
|
|
148
|
+
case "AuthenticationFailed": {
|
|
149
|
+
const user = err.cause.user ?? "(not available)";
|
|
150
|
+
return `Authentication failed against the database server, the provided database credentials for \`${user}\` are not valid`;
|
|
151
|
+
}
|
|
152
|
+
case "DatabaseDoesNotExist": {
|
|
153
|
+
const db = err.cause.db ?? "(not available)";
|
|
154
|
+
return `Database \`${db}\` does not exist on the database server`;
|
|
155
|
+
}
|
|
156
|
+
case "SocketTimeout":
|
|
157
|
+
return `Operation has timed out`;
|
|
158
|
+
case "DatabaseAlreadyExists": {
|
|
159
|
+
const db = err.cause.db ?? "(not available)";
|
|
160
|
+
return `Database \`${db}\` already exists on the database server`;
|
|
161
|
+
}
|
|
162
|
+
case "DatabaseAccessDenied": {
|
|
163
|
+
const db = err.cause.db ?? "(not available)";
|
|
164
|
+
return `User was denied access on the database \`${db}\``;
|
|
165
|
+
}
|
|
166
|
+
case "LengthMismatch": {
|
|
167
|
+
const column = err.cause.column ?? "(not available)";
|
|
168
|
+
return `The provided value for the column is too long for the column's type. Column: ${column}`;
|
|
169
|
+
}
|
|
170
|
+
case "UniqueConstraintViolation":
|
|
171
|
+
return `Unique constraint failed on the ${renderConstraint({ fields: err.cause.fields })}`;
|
|
172
|
+
case "ForeignKeyConstraintViolation":
|
|
173
|
+
return `Foreign key constraint violated on the ${renderConstraint(err.cause.constraint)}`;
|
|
174
|
+
case "UnsupportedNativeDataType":
|
|
175
|
+
return `Failed to deserialize column of type '${err.cause.type}'. If you're using $queryRaw and this column is explicitly marked as \`Unsupported\` in your Prisma schema, try casting this column to any supported Prisma type such as \`String\`.`;
|
|
176
|
+
case "NullConstraintViolation":
|
|
177
|
+
return `Null constraint violation on the ${renderConstraint({ fields: err.cause.fields })}`;
|
|
178
|
+
case "TableDoesNotExist": {
|
|
179
|
+
const table = err.cause.table ?? "(not available)";
|
|
180
|
+
return `The table \`${table}\` does not exist in the current database.`;
|
|
181
|
+
}
|
|
182
|
+
case "ColumnNotFound": {
|
|
183
|
+
const column = err.cause.column ?? "(not available)";
|
|
184
|
+
return `The column \`${column}\` does not exist in the current database.`;
|
|
185
|
+
}
|
|
186
|
+
case "InvalidIsolationLevel":
|
|
187
|
+
return `Invalid isolation level \`${err.cause.level}\``;
|
|
188
|
+
case "TransactionWriteConflict":
|
|
189
|
+
return `Transaction failed due to a write conflict or a deadlock. Please retry your transaction`;
|
|
190
|
+
case "GenericJs":
|
|
191
|
+
return `Error in external connector (id ${err.cause.id})`;
|
|
192
|
+
case "TooManyConnections":
|
|
193
|
+
return `Too many database connections opened: ${err.cause.cause}`;
|
|
194
|
+
case "sqlite":
|
|
195
|
+
case "postgres":
|
|
196
|
+
case "mysql":
|
|
197
|
+
return;
|
|
198
|
+
default:
|
|
199
|
+
assertNever(err.cause, `Unknown error: ${err.cause}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function renderConstraint(constraint) {
|
|
203
|
+
if (constraint && "fields" in constraint) {
|
|
204
|
+
return `fields: (${constraint.fields.map((field) => `\`${field}\``).join(", ")})`;
|
|
205
|
+
} else if (constraint && "index" in constraint) {
|
|
206
|
+
return `constraint: \`${constraint.index}\``;
|
|
207
|
+
} else if (constraint && "foreignKey" in constraint) {
|
|
208
|
+
return `foreign key`;
|
|
209
|
+
}
|
|
210
|
+
return "(not available)";
|
|
211
|
+
}
|
|
212
|
+
|
|
41
213
|
// src/interpreter/generators.ts
|
|
42
214
|
var import_cuid = __toESM(require("@bugsnag/cuid"));
|
|
43
215
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
@@ -52,6 +224,7 @@ var GeneratorRegistry = class {
|
|
|
52
224
|
this.register("cuid", new CuidGenerator());
|
|
53
225
|
this.register("ulid", new UlidGenerator());
|
|
54
226
|
this.register("nanoid", new NanoIdGenerator());
|
|
227
|
+
this.register("product", new ProductGenerator());
|
|
55
228
|
}
|
|
56
229
|
/**
|
|
57
230
|
* Returns a snapshot of the generator registry. It's 'frozen' in time at the moment of this
|
|
@@ -114,6 +287,22 @@ var NanoIdGenerator = class {
|
|
|
114
287
|
}
|
|
115
288
|
}
|
|
116
289
|
};
|
|
290
|
+
var ProductGenerator = class {
|
|
291
|
+
generate(lhs, rhs) {
|
|
292
|
+
if (lhs === void 0 || rhs === void 0) {
|
|
293
|
+
throw new Error("Invalid Product generator arguments");
|
|
294
|
+
}
|
|
295
|
+
if (Array.isArray(lhs) && Array.isArray(rhs)) {
|
|
296
|
+
return lhs.flatMap((l) => rhs.map((r) => [l, r]));
|
|
297
|
+
} else if (Array.isArray(lhs)) {
|
|
298
|
+
return lhs.map((l) => [l, rhs]);
|
|
299
|
+
} else if (Array.isArray(rhs)) {
|
|
300
|
+
return rhs.map((r) => [lhs, r]);
|
|
301
|
+
} else {
|
|
302
|
+
return [[lhs, rhs]];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
};
|
|
117
306
|
|
|
118
307
|
// src/QueryPlan.ts
|
|
119
308
|
function isPrismaValuePlaceholder(value) {
|
|
@@ -123,46 +312,49 @@ function isPrismaValueGenerator(value) {
|
|
|
123
312
|
return typeof value === "object" && value !== null && value["prisma__type"] === "generatorCall";
|
|
124
313
|
}
|
|
125
314
|
|
|
126
|
-
// src/utils.ts
|
|
127
|
-
function assertNever(_, message) {
|
|
128
|
-
throw new Error(message);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
315
|
// src/interpreter/renderQuery.ts
|
|
132
316
|
function renderQuery(dbQuery, scope, generators) {
|
|
133
317
|
const queryType = dbQuery.type;
|
|
134
318
|
switch (queryType) {
|
|
135
319
|
case "rawSql":
|
|
136
|
-
return renderRawSql(dbQuery.sql,
|
|
320
|
+
return renderRawSql(dbQuery.sql, evaluateParams(dbQuery.params, scope, generators));
|
|
137
321
|
case "templateSql":
|
|
138
322
|
return renderTemplateSql(
|
|
139
323
|
dbQuery.fragments,
|
|
140
324
|
dbQuery.placeholderFormat,
|
|
141
|
-
|
|
325
|
+
evaluateParams(dbQuery.params, scope, generators)
|
|
142
326
|
);
|
|
143
327
|
default:
|
|
144
328
|
assertNever(queryType, `Invalid query type`);
|
|
145
329
|
}
|
|
146
330
|
}
|
|
147
|
-
function
|
|
148
|
-
return params.map((param) =>
|
|
149
|
-
|
|
150
|
-
|
|
331
|
+
function evaluateParams(params, scope, generators) {
|
|
332
|
+
return params.map((param) => evaluateParam(param, scope, generators));
|
|
333
|
+
}
|
|
334
|
+
function evaluateParam(param, scope, generators) {
|
|
335
|
+
let value = param;
|
|
336
|
+
while (doesRequireEvaluation(value)) {
|
|
337
|
+
if (isPrismaValuePlaceholder(value)) {
|
|
338
|
+
const found = scope[value.prisma__value.name];
|
|
339
|
+
if (found === void 0) {
|
|
340
|
+
throw new Error(`Missing value for query variable ${value.prisma__value.name}`);
|
|
341
|
+
}
|
|
342
|
+
value = found;
|
|
343
|
+
} else if (isPrismaValueGenerator(value)) {
|
|
344
|
+
const { name, args } = value.prisma__value;
|
|
151
345
|
const generator = generators[name];
|
|
152
346
|
if (!generator) {
|
|
153
347
|
throw new Error(`Encountered an unknown generator '${name}'`);
|
|
154
348
|
}
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return param;
|
|
159
|
-
}
|
|
160
|
-
const value = scope[param.prisma__value.name];
|
|
161
|
-
if (value === void 0) {
|
|
162
|
-
throw new Error(`Missing value for query variable ${param.prisma__value.name}`);
|
|
349
|
+
value = generator.generate(...args.map((arg) => evaluateParam(arg, scope, generators)));
|
|
350
|
+
} else {
|
|
351
|
+
assertNever(value, `Unexpected unevaluated value type: ${value}`);
|
|
163
352
|
}
|
|
164
|
-
|
|
165
|
-
|
|
353
|
+
}
|
|
354
|
+
if (Array.isArray(value)) {
|
|
355
|
+
value = value.map((el) => evaluateParam(el, scope, generators));
|
|
356
|
+
}
|
|
357
|
+
return value;
|
|
166
358
|
}
|
|
167
359
|
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
168
360
|
let paramIndex = 0;
|
|
@@ -191,6 +383,29 @@ function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
|
191
383
|
}).join(",");
|
|
192
384
|
return `(${placeholders})`;
|
|
193
385
|
}
|
|
386
|
+
case "parameterTupleList": {
|
|
387
|
+
if (paramIndex >= params.length) {
|
|
388
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
389
|
+
}
|
|
390
|
+
const paramValue = params[paramIndex++];
|
|
391
|
+
if (!Array.isArray(paramValue)) {
|
|
392
|
+
throw new Error(`Malformed query template. Tuple list expected.`);
|
|
393
|
+
}
|
|
394
|
+
if (paramValue.length === 0) {
|
|
395
|
+
throw new Error(`Malformed query template. Tuple list cannot be empty.`);
|
|
396
|
+
}
|
|
397
|
+
const tupleList = paramValue.map((tuple) => {
|
|
398
|
+
if (!Array.isArray(tuple)) {
|
|
399
|
+
throw new Error(`Malformed query template. Tuple expected.`);
|
|
400
|
+
}
|
|
401
|
+
const elements = tuple.map((value) => {
|
|
402
|
+
flattenedParams.push(value);
|
|
403
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
404
|
+
}).join(",");
|
|
405
|
+
return `(${elements})`;
|
|
406
|
+
}).join(",");
|
|
407
|
+
return tupleList;
|
|
408
|
+
}
|
|
194
409
|
default:
|
|
195
410
|
assertNever(fragmentType, "Invalid fragment type");
|
|
196
411
|
}
|
|
@@ -249,6 +464,9 @@ function placeholderTypeToArgType(type) {
|
|
|
249
464
|
}
|
|
250
465
|
return mappedType;
|
|
251
466
|
}
|
|
467
|
+
function doesRequireEvaluation(param) {
|
|
468
|
+
return isPrismaValuePlaceholder(param) || isPrismaValueGenerator(param);
|
|
469
|
+
}
|
|
252
470
|
|
|
253
471
|
// src/interpreter/serialize.ts
|
|
254
472
|
function serialize(resultSet) {
|
|
@@ -278,13 +496,17 @@ var QueryInterpreter = class {
|
|
|
278
496
|
#placeholderValues;
|
|
279
497
|
#onQuery;
|
|
280
498
|
#generators = new GeneratorRegistry();
|
|
281
|
-
|
|
499
|
+
#tracingHelper;
|
|
500
|
+
constructor({ transactionManager, placeholderValues, onQuery, tracingHelper }) {
|
|
282
501
|
this.#transactionManager = transactionManager;
|
|
283
502
|
this.#placeholderValues = placeholderValues;
|
|
284
503
|
this.#onQuery = onQuery;
|
|
504
|
+
this.#tracingHelper = tracingHelper;
|
|
285
505
|
}
|
|
286
506
|
async run(queryPlan, queryable) {
|
|
287
|
-
return this.interpretNode(queryPlan, queryable, this.#placeholderValues, this.#generators.snapshot())
|
|
507
|
+
return this.interpretNode(queryPlan, queryable, this.#placeholderValues, this.#generators.snapshot()).catch(
|
|
508
|
+
(e) => rethrowAsUserFacing(e)
|
|
509
|
+
);
|
|
288
510
|
}
|
|
289
511
|
async interpretNode(node, queryable, scope, generators) {
|
|
290
512
|
switch (node.type) {
|
|
@@ -323,13 +545,13 @@ var QueryInterpreter = class {
|
|
|
323
545
|
}
|
|
324
546
|
case "execute": {
|
|
325
547
|
const query = renderQuery(node.args, scope, generators);
|
|
326
|
-
return this.#withQueryEvent(query, async () => {
|
|
548
|
+
return this.#withQueryEvent(query, queryable, async () => {
|
|
327
549
|
return await queryable.executeRaw(query);
|
|
328
550
|
});
|
|
329
551
|
}
|
|
330
552
|
case "query": {
|
|
331
553
|
const query = renderQuery(node.args, scope, generators);
|
|
332
|
-
return this.#withQueryEvent(query, async () => {
|
|
554
|
+
return this.#withQueryEvent(query, queryable, async () => {
|
|
333
555
|
return serialize(await queryable.queryRaw(query));
|
|
334
556
|
});
|
|
335
557
|
}
|
|
@@ -390,24 +612,34 @@ var QueryInterpreter = class {
|
|
|
390
612
|
throw e;
|
|
391
613
|
}
|
|
392
614
|
}
|
|
393
|
-
default:
|
|
394
|
-
node;
|
|
395
|
-
throw new Error(`Unexpected node type: ${node.type}`);
|
|
396
|
-
}
|
|
615
|
+
default:
|
|
616
|
+
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
397
617
|
}
|
|
398
618
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
619
|
+
#withQueryEvent(query, queryable, execute) {
|
|
620
|
+
return this.#tracingHelper.runInChildSpan(
|
|
621
|
+
{
|
|
622
|
+
name: "db_query",
|
|
623
|
+
kind: import_api.SpanKind.CLIENT,
|
|
624
|
+
attributes: {
|
|
625
|
+
"db.query.text": query.sql,
|
|
626
|
+
"db.system.name": providerToOtelSystem(queryable.provider)
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
async () => {
|
|
630
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
631
|
+
const startInstant = performance.now();
|
|
632
|
+
const result = await execute();
|
|
633
|
+
const endInstant = performance.now();
|
|
634
|
+
this.#onQuery?.({
|
|
635
|
+
timestamp,
|
|
636
|
+
duration: endInstant - startInstant,
|
|
637
|
+
query: query.sql,
|
|
638
|
+
params: query.args
|
|
639
|
+
});
|
|
640
|
+
return result;
|
|
641
|
+
}
|
|
642
|
+
);
|
|
411
643
|
}
|
|
412
644
|
};
|
|
413
645
|
function isEmpty(value) {
|
|
@@ -452,6 +684,8 @@ function attachChildrenToParent(parentRecord, children) {
|
|
|
452
684
|
function filterChildRecords(records, parentRecord, joinExpr) {
|
|
453
685
|
if (Array.isArray(records)) {
|
|
454
686
|
return records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
|
|
687
|
+
} else if (records === null) {
|
|
688
|
+
return null;
|
|
455
689
|
} else {
|
|
456
690
|
const record = asRecord(records);
|
|
457
691
|
return childRecordMatchesParent(record, parentRecord, joinExpr) ? record : null;
|
|
@@ -486,11 +720,6 @@ var TransactionManagerError = class extends Error {
|
|
|
486
720
|
}
|
|
487
721
|
code = "P2028";
|
|
488
722
|
};
|
|
489
|
-
var TransactionDriverAdapterError = class extends TransactionManagerError {
|
|
490
|
-
constructor(message, errorParams) {
|
|
491
|
-
super(`Error from Driver Adapter: ${message}`, { ...errorParams.driverAdapterError });
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
723
|
var TransactionNotFoundError = class extends TransactionManagerError {
|
|
495
724
|
constructor() {
|
|
496
725
|
super(
|
|
@@ -508,7 +737,7 @@ var TransactionRolledBackError = class extends TransactionManagerError {
|
|
|
508
737
|
super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction`);
|
|
509
738
|
}
|
|
510
739
|
};
|
|
511
|
-
var
|
|
740
|
+
var TransactionStartTimeoutError = class extends TransactionManagerError {
|
|
512
741
|
constructor() {
|
|
513
742
|
super("Unable to start a transaction in the given time.");
|
|
514
743
|
}
|
|
@@ -545,11 +774,20 @@ var TransactionManager = class {
|
|
|
545
774
|
closedTransactions = [];
|
|
546
775
|
driverAdapter;
|
|
547
776
|
transactionOptions;
|
|
548
|
-
|
|
777
|
+
tracingHelper;
|
|
778
|
+
constructor({
|
|
779
|
+
driverAdapter,
|
|
780
|
+
transactionOptions,
|
|
781
|
+
tracingHelper
|
|
782
|
+
}) {
|
|
549
783
|
this.driverAdapter = driverAdapter;
|
|
550
784
|
this.transactionOptions = transactionOptions;
|
|
785
|
+
this.tracingHelper = tracingHelper;
|
|
551
786
|
}
|
|
552
787
|
async startTransaction(options) {
|
|
788
|
+
return await this.tracingHelper.runInChildSpan("start_transaction", () => this.#startTransactionImpl(options));
|
|
789
|
+
}
|
|
790
|
+
async #startTransactionImpl(options) {
|
|
553
791
|
const validatedOptions = options !== void 0 ? this.validateOptions(options) : this.transactionOptions;
|
|
554
792
|
const transaction = {
|
|
555
793
|
id: await randomUUID(),
|
|
@@ -561,14 +799,7 @@ var TransactionManager = class {
|
|
|
561
799
|
};
|
|
562
800
|
this.transactions.set(transaction.id, transaction);
|
|
563
801
|
transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.maxWait);
|
|
564
|
-
|
|
565
|
-
try {
|
|
566
|
-
startedTransaction = await this.driverAdapter.startTransaction(validatedOptions.isolationLevel);
|
|
567
|
-
} catch (error) {
|
|
568
|
-
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
569
|
-
driverAdapterError: error
|
|
570
|
-
});
|
|
571
|
-
}
|
|
802
|
+
const startedTransaction = await this.driverAdapter.startTransaction(validatedOptions.isolationLevel);
|
|
572
803
|
switch (transaction.status) {
|
|
573
804
|
case "waiting":
|
|
574
805
|
transaction.transaction = startedTransaction;
|
|
@@ -578,7 +809,7 @@ var TransactionManager = class {
|
|
|
578
809
|
transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.timeout);
|
|
579
810
|
return { id: transaction.id };
|
|
580
811
|
case "timed_out":
|
|
581
|
-
throw new
|
|
812
|
+
throw new TransactionStartTimeoutError();
|
|
582
813
|
case "running":
|
|
583
814
|
case "committed":
|
|
584
815
|
case "rolled_back":
|
|
@@ -590,12 +821,16 @@ var TransactionManager = class {
|
|
|
590
821
|
}
|
|
591
822
|
}
|
|
592
823
|
async commitTransaction(transactionId) {
|
|
593
|
-
|
|
594
|
-
|
|
824
|
+
return await this.tracingHelper.runInChildSpan("commit_transaction", async () => {
|
|
825
|
+
const txw = this.getActiveTransaction(transactionId, "commit");
|
|
826
|
+
await this.closeTransaction(txw, "committed");
|
|
827
|
+
});
|
|
595
828
|
}
|
|
596
829
|
async rollbackTransaction(transactionId) {
|
|
597
|
-
|
|
598
|
-
|
|
830
|
+
return await this.tracingHelper.runInChildSpan("rollback_transaction", async () => {
|
|
831
|
+
const txw = this.getActiveTransaction(transactionId, "rollback");
|
|
832
|
+
await this.closeTransaction(txw, "rolled_back");
|
|
833
|
+
});
|
|
599
834
|
}
|
|
600
835
|
getTransaction(txInfo, operation) {
|
|
601
836
|
const tx = this.getActiveTransaction(txInfo.id, operation);
|
|
@@ -651,24 +886,12 @@ var TransactionManager = class {
|
|
|
651
886
|
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
652
887
|
tx.status = status;
|
|
653
888
|
if (tx.transaction && status === "committed") {
|
|
654
|
-
|
|
655
|
-
await tx.transaction.commit();
|
|
656
|
-
} catch (error) {
|
|
657
|
-
throw new TransactionDriverAdapterError("Failed to commit transaction.", {
|
|
658
|
-
driverAdapterError: error
|
|
659
|
-
});
|
|
660
|
-
}
|
|
889
|
+
await tx.transaction.commit();
|
|
661
890
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
662
891
|
await tx.transaction.executeRaw(COMMIT_QUERY());
|
|
663
892
|
}
|
|
664
893
|
} else if (tx.transaction) {
|
|
665
|
-
|
|
666
|
-
await tx.transaction.rollback();
|
|
667
|
-
} catch (error) {
|
|
668
|
-
throw new TransactionDriverAdapterError("Failed to rollback transaction.", {
|
|
669
|
-
driverAdapterError: error
|
|
670
|
-
});
|
|
671
|
-
}
|
|
894
|
+
await tx.transaction.rollback();
|
|
672
895
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
673
896
|
await tx.transaction.executeRaw(ROLLBACK_QUERY());
|
|
674
897
|
}
|
|
@@ -697,6 +920,8 @@ var TransactionManager = class {
|
|
|
697
920
|
QueryInterpreter,
|
|
698
921
|
TransactionManager,
|
|
699
922
|
TransactionManagerError,
|
|
923
|
+
UserFacingError,
|
|
700
924
|
isPrismaValueGenerator,
|
|
701
|
-
isPrismaValuePlaceholder
|
|
925
|
+
isPrismaValuePlaceholder,
|
|
926
|
+
noopTracingHelper
|
|
702
927
|
});
|