monsqlize 3.3.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.
@@ -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 isUnknownTransactionCommitResult(error) {
357
- if (!error || typeof error !== "object") {
358
- return false;
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
- const candidate = error;
361
- return typeof candidate.hasErrorLabel === "function" && candidate.hasErrorLabel("UnknownTransactionCommitResult");
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
- if (!enableRetry || attempt === maxRetries || !isTransientTransactionError(error)) {
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 isTransientTransactionError(error) {
526
- if (!error || typeof error !== "object") {
527
- return false;
528
- }
529
- const candidate = error;
530
- if (typeof candidate.hasErrorLabel === "function" && candidate.hasErrorLabel("TransientTransactionError")) {
531
- return true;
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 candidate.code === 112 || candidate.code === 117;
555
+ return false;
534
556
  }
535
557
  function isUnknownTransactionCommitResult(error) {
536
- if (!error || typeof error !== "object") {
537
- return false;
538
- }
539
- const candidate = error;
540
- return typeof candidate.hasErrorLabel === "function" && candidate.hasErrorLabel("UnknownTransactionCommitResult");
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;