monsqlize 3.2.0 → 3.3.1
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 +8 -2
- package/README.md +56 -6
- package/changelogs/v3.3.0.md +29 -0
- package/changelogs/v3.3.1.md +28 -0
- package/dist/cjs/cli/data-task.cjs +5 -3
- package/dist/cjs/index.cjs +1037 -630
- package/dist/cjs/transaction/Transaction.cjs +33 -5
- package/dist/cjs/transaction/TransactionManager.cjs +38 -16
- package/dist/esm/index.mjs +1042 -634
- package/dist/types/collection.d.mts +6 -6
- package/dist/types/collection.d.ts +6 -6
- package/dist/types/data-tasks.d.mts +1 -0
- package/dist/types/data-tasks.d.ts +1 -0
- package/dist/types/model.d.mts +42 -0
- package/dist/types/model.d.ts +42 -0
- package/dist/types/monsqlize.d.mts +32 -9
- package/dist/types/monsqlize.d.ts +32 -9
- package/dist/types/runtime.d.mts +3 -1
- package/dist/types/runtime.d.ts +3 -1
- package/licenses/production-dependencies.json +1 -1
- package/package.json +5 -3
|
@@ -150,6 +150,7 @@ var Transaction = class {
|
|
|
150
150
|
this.options = options;
|
|
151
151
|
this.id = `tx_${(0, import_node_crypto.randomBytes)(8).toString("hex")}`;
|
|
152
152
|
this.state = "pending";
|
|
153
|
+
this.acceptingWrites = false;
|
|
153
154
|
this.startedAt = null;
|
|
154
155
|
this.timeoutTimer = null;
|
|
155
156
|
this.pendingInvalidations = /* @__PURE__ */ new Set();
|
|
@@ -168,6 +169,7 @@ var Transaction = class {
|
|
|
168
169
|
}
|
|
169
170
|
this.session.startTransaction(this.options.transactionOptions);
|
|
170
171
|
this.state = "active";
|
|
172
|
+
this.acceptingWrites = true;
|
|
171
173
|
this.startedAt = Date.now();
|
|
172
174
|
const timeout = this.options.timeout ?? 3e4;
|
|
173
175
|
if (timeout > 0) {
|
|
@@ -190,6 +192,7 @@ var Transaction = class {
|
|
|
190
192
|
if (this.state !== "active") {
|
|
191
193
|
throw createError(ErrorCodes.INVALID_OPERATION, `Cannot commit transaction in state: ${this.state}`);
|
|
192
194
|
}
|
|
195
|
+
this.acceptingWrites = false;
|
|
193
196
|
if (typeof this.session.commitTransaction === "function") {
|
|
194
197
|
await commitTransactionWithRetry(this.session, this.options.logger);
|
|
195
198
|
}
|
|
@@ -215,6 +218,7 @@ var Transaction = class {
|
|
|
215
218
|
* @since v1.4.0
|
|
216
219
|
*/
|
|
217
220
|
async abort() {
|
|
221
|
+
this.acceptingWrites = false;
|
|
218
222
|
if (this.state !== "pending" && this.state !== "active") {
|
|
219
223
|
return;
|
|
220
224
|
}
|
|
@@ -239,10 +243,16 @@ var Transaction = class {
|
|
|
239
243
|
* @since v1.4.0
|
|
240
244
|
*/
|
|
241
245
|
async end() {
|
|
246
|
+
this.acceptingWrites = false;
|
|
242
247
|
this.clearTimeout();
|
|
243
248
|
this.options.lockManager?.releaseLocks(this.id);
|
|
244
249
|
await this.session.endSession();
|
|
245
250
|
}
|
|
251
|
+
assertAcceptingWrites() {
|
|
252
|
+
if (this.state !== "active" || !this.acceptingWrites) {
|
|
253
|
+
throw createError(ErrorCodes.INVALID_OPERATION, `Managed transaction ${this.id} is no longer accepting writes.`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
246
256
|
/**
|
|
247
257
|
* Record a cache invalidation intent.
|
|
248
258
|
* @since v1.4.0
|
|
@@ -353,12 +363,30 @@ function stringifySessionId(id) {
|
|
|
353
363
|
}
|
|
354
364
|
return String(id);
|
|
355
365
|
}
|
|
356
|
-
function
|
|
357
|
-
|
|
358
|
-
|
|
366
|
+
function transactionErrorChain(error) {
|
|
367
|
+
const chain = [];
|
|
368
|
+
const seen = /* @__PURE__ */ new Set();
|
|
369
|
+
let current = error;
|
|
370
|
+
while (current && typeof current === "object" && chain.length < 8 && !seen.has(current)) {
|
|
371
|
+
seen.add(current);
|
|
372
|
+
const candidate = current;
|
|
373
|
+
chain.push(candidate);
|
|
374
|
+
current = candidate.cause;
|
|
359
375
|
}
|
|
360
|
-
|
|
361
|
-
|
|
376
|
+
return chain;
|
|
377
|
+
}
|
|
378
|
+
function hasTransactionErrorLabel(candidate, label) {
|
|
379
|
+
if (Array.isArray(candidate.errorLabels) && candidate.errorLabels.includes(label)) return true;
|
|
380
|
+
if (typeof candidate.hasErrorLabel === "function") {
|
|
381
|
+
try {
|
|
382
|
+
return Boolean(candidate.hasErrorLabel.call(candidate, label));
|
|
383
|
+
} catch {
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
function isUnknownTransactionCommitResult(error) {
|
|
389
|
+
return transactionErrorChain(error).some((candidate) => hasTransactionErrorLabel(candidate, "UnknownTransactionCommitResult"));
|
|
362
390
|
}
|
|
363
391
|
async function commitTransactionWithRetry(session, logger) {
|
|
364
392
|
const maxAttempts = 3;
|
|
@@ -150,6 +150,7 @@ var Transaction = class {
|
|
|
150
150
|
this.options = options;
|
|
151
151
|
this.id = `tx_${(0, import_node_crypto.randomBytes)(8).toString("hex")}`;
|
|
152
152
|
this.state = "pending";
|
|
153
|
+
this.acceptingWrites = false;
|
|
153
154
|
this.startedAt = null;
|
|
154
155
|
this.timeoutTimer = null;
|
|
155
156
|
this.pendingInvalidations = /* @__PURE__ */ new Set();
|
|
@@ -168,6 +169,7 @@ var Transaction = class {
|
|
|
168
169
|
}
|
|
169
170
|
this.session.startTransaction(this.options.transactionOptions);
|
|
170
171
|
this.state = "active";
|
|
172
|
+
this.acceptingWrites = true;
|
|
171
173
|
this.startedAt = Date.now();
|
|
172
174
|
const timeout = this.options.timeout ?? 3e4;
|
|
173
175
|
if (timeout > 0) {
|
|
@@ -190,6 +192,7 @@ var Transaction = class {
|
|
|
190
192
|
if (this.state !== "active") {
|
|
191
193
|
throw createError(ErrorCodes.INVALID_OPERATION, `Cannot commit transaction in state: ${this.state}`);
|
|
192
194
|
}
|
|
195
|
+
this.acceptingWrites = false;
|
|
193
196
|
if (typeof this.session.commitTransaction === "function") {
|
|
194
197
|
await commitTransactionWithRetry(this.session, this.options.logger);
|
|
195
198
|
}
|
|
@@ -215,6 +218,7 @@ var Transaction = class {
|
|
|
215
218
|
* @since v1.4.0
|
|
216
219
|
*/
|
|
217
220
|
async abort() {
|
|
221
|
+
this.acceptingWrites = false;
|
|
218
222
|
if (this.state !== "pending" && this.state !== "active") {
|
|
219
223
|
return;
|
|
220
224
|
}
|
|
@@ -239,10 +243,16 @@ var Transaction = class {
|
|
|
239
243
|
* @since v1.4.0
|
|
240
244
|
*/
|
|
241
245
|
async end() {
|
|
246
|
+
this.acceptingWrites = false;
|
|
242
247
|
this.clearTimeout();
|
|
243
248
|
this.options.lockManager?.releaseLocks(this.id);
|
|
244
249
|
await this.session.endSession();
|
|
245
250
|
}
|
|
251
|
+
assertAcceptingWrites() {
|
|
252
|
+
if (this.state !== "active" || !this.acceptingWrites) {
|
|
253
|
+
throw createError(ErrorCodes.INVALID_OPERATION, `Managed transaction ${this.id} is no longer accepting writes.`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
246
256
|
/**
|
|
247
257
|
* Record a cache invalidation intent.
|
|
248
258
|
* @since v1.4.0
|
|
@@ -416,12 +426,12 @@ var TransactionManager = class {
|
|
|
416
426
|
return result;
|
|
417
427
|
} catch (error) {
|
|
418
428
|
lastError = error;
|
|
419
|
-
await transaction.abort();
|
|
420
|
-
this.recordStats(transaction, Date.now() - startedAt, false);
|
|
421
429
|
if (transaction.state === "committed") {
|
|
422
430
|
throw error;
|
|
423
431
|
}
|
|
424
|
-
|
|
432
|
+
await transaction.abort();
|
|
433
|
+
this.recordStats(transaction, Date.now() - startedAt, false);
|
|
434
|
+
if (!enableRetry || attempt === maxRetries || isUnknownTransactionCommitResult(error) || !isTransientTransactionError(error)) {
|
|
425
435
|
throw error;
|
|
426
436
|
}
|
|
427
437
|
await sleep(retryDelay * Math.pow(retryBackoff, attempt));
|
|
@@ -522,22 +532,34 @@ function stringifySessionId(id) {
|
|
|
522
532
|
}
|
|
523
533
|
return String(id);
|
|
524
534
|
}
|
|
525
|
-
function
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
535
|
+
function transactionErrorChain(error) {
|
|
536
|
+
const chain = [];
|
|
537
|
+
const seen = /* @__PURE__ */ new Set();
|
|
538
|
+
let current = error;
|
|
539
|
+
while (current && typeof current === "object" && chain.length < 8 && !seen.has(current)) {
|
|
540
|
+
seen.add(current);
|
|
541
|
+
const candidate = current;
|
|
542
|
+
chain.push(candidate);
|
|
543
|
+
current = candidate.cause;
|
|
544
|
+
}
|
|
545
|
+
return chain;
|
|
546
|
+
}
|
|
547
|
+
function hasTransactionErrorLabel(candidate, label) {
|
|
548
|
+
if (Array.isArray(candidate.errorLabels) && candidate.errorLabels.includes(label)) return true;
|
|
549
|
+
if (typeof candidate.hasErrorLabel === "function") {
|
|
550
|
+
try {
|
|
551
|
+
return Boolean(candidate.hasErrorLabel.call(candidate, label));
|
|
552
|
+
} catch {
|
|
553
|
+
}
|
|
532
554
|
}
|
|
533
|
-
return
|
|
555
|
+
return false;
|
|
534
556
|
}
|
|
535
557
|
function isUnknownTransactionCommitResult(error) {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
return
|
|
558
|
+
return transactionErrorChain(error).some((candidate) => hasTransactionErrorLabel(candidate, "UnknownTransactionCommitResult"));
|
|
559
|
+
}
|
|
560
|
+
function isTransientTransactionError(error) {
|
|
561
|
+
if (isUnknownTransactionCommitResult(error)) return false;
|
|
562
|
+
return transactionErrorChain(error).some((candidate) => hasTransactionErrorLabel(candidate, "TransientTransactionError") || candidate.code === 112 || candidate.code === 117 || candidate.codeName === "WriteConflict" || candidate.codeName === "LockTimeout");
|
|
541
563
|
}
|
|
542
564
|
async function commitTransactionWithRetry(session, logger) {
|
|
543
565
|
const maxAttempts = 3;
|