mongodb 7.0.0-dev.20251211.sha.f88bfe18 → 7.0.0-dev.20251217.sha.c990750f
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/lib/cmap/connect.js +15 -0
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection_pool.js +6 -6
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/error.js +3 -1
- package/lib/error.js.map +1 -1
- package/lib/gridfs/upload.js +8 -8
- package/lib/gridfs/upload.js.map +1 -1
- package/lib/sdam/monitor.js +1 -1
- package/lib/sdam/monitor.js.map +1 -1
- package/lib/sdam/server.js +8 -3
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/topology.js +1 -1
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +28 -2
- package/lib/sessions.js.map +1 -1
- package/mongodb.d.ts +2 -0
- package/package.json +1 -1
- package/src/cmap/connect.ts +19 -0
- package/src/cmap/connection_pool.ts +6 -6
- package/src/error.ts +3 -1
- package/src/gridfs/upload.ts +8 -8
- package/src/sdam/monitor.ts +1 -1
- package/src/sdam/server.ts +8 -3
- package/src/sdam/topology.ts +1 -1
- package/src/sessions.ts +28 -2
package/src/sdam/server.ts
CHANGED
|
@@ -400,7 +400,8 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
400
400
|
error instanceof MongoNetworkError && !(error instanceof MongoNetworkTimeoutError);
|
|
401
401
|
const isNetworkTimeoutBeforeHandshakeError =
|
|
402
402
|
error instanceof MongoNetworkError && error.beforeHandshake;
|
|
403
|
-
const
|
|
403
|
+
const isAuthOrEstablishmentHandshakeError = error.hasErrorLabel(MongoErrorLabel.HandshakeError);
|
|
404
|
+
const isSystemOverloadError = error.hasErrorLabel(MongoErrorLabel.SystemOverloadedError);
|
|
404
405
|
|
|
405
406
|
// Perhaps questionable and divergent from the spec, but considering MongoParseErrors like state change errors was legacy behavior.
|
|
406
407
|
if (isStateChangeError(error) || error instanceof MongoParseError) {
|
|
@@ -414,7 +415,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
414
415
|
error.addErrorLabel(MongoErrorLabel.ResetPool);
|
|
415
416
|
}
|
|
416
417
|
markServerUnknown(this, error);
|
|
417
|
-
|
|
418
|
+
queueMicrotask(() => this.requestCheck());
|
|
418
419
|
return;
|
|
419
420
|
}
|
|
420
421
|
|
|
@@ -424,8 +425,12 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
424
425
|
} else if (
|
|
425
426
|
isNetworkNonTimeoutError ||
|
|
426
427
|
isNetworkTimeoutBeforeHandshakeError ||
|
|
427
|
-
|
|
428
|
+
isAuthOrEstablishmentHandshakeError
|
|
428
429
|
) {
|
|
430
|
+
// Do NOT clear the pool if we encounter a system overloaded error.
|
|
431
|
+
if (isSystemOverloadError) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
429
434
|
// from the SDAM spec: The driver MUST synchronize clearing the pool with updating the topology.
|
|
430
435
|
// In load balanced mode: there is no monitoring, so there is no topology to update. We simply clear the pool.
|
|
431
436
|
// For other topologies: the `ResetPool` label instructs the topology to clear the server's pool in `updateServer()`.
|
package/src/sdam/topology.ts
CHANGED
|
@@ -1076,7 +1076,7 @@ function processWaitQueue(topology: Topology) {
|
|
|
1076
1076
|
if (topology.waitQueue.length > 0) {
|
|
1077
1077
|
// ensure all server monitors attempt monitoring soon
|
|
1078
1078
|
for (const [, server] of topology.s.servers) {
|
|
1079
|
-
|
|
1079
|
+
queueMicrotask(function scheduleServerCheck() {
|
|
1080
1080
|
return server.requestCheck();
|
|
1081
1081
|
});
|
|
1082
1082
|
}
|
package/src/sessions.ts
CHANGED
|
@@ -726,7 +726,8 @@ export class ClientSession
|
|
|
726
726
|
})
|
|
727
727
|
: null;
|
|
728
728
|
|
|
729
|
-
|
|
729
|
+
// 1. Record the current monotonic time, which will be used to enforce the 120-second timeout before later retry attempts.
|
|
730
|
+
const startTime = this.timeoutContext?.csotEnabled() // This is strictly to appease TS. We must narrow the context to a CSOT context before accessing `.start`.
|
|
730
731
|
? this.timeoutContext.start
|
|
731
732
|
: processTimeMS();
|
|
732
733
|
|
|
@@ -735,9 +736,13 @@ export class ClientSession
|
|
|
735
736
|
|
|
736
737
|
try {
|
|
737
738
|
while (!committed) {
|
|
739
|
+
// 2. Invoke startTransaction on the session
|
|
740
|
+
// 3. If `startTransaction` reported an error, propagate that error to the caller of `withTransaction` and return immediately.
|
|
738
741
|
this.startTransaction(options); // may throw on error
|
|
739
742
|
|
|
740
743
|
try {
|
|
744
|
+
// 4. Invoke the callback.
|
|
745
|
+
// 5. Control returns to withTransaction. (continued below)
|
|
741
746
|
const promise = fn(this);
|
|
742
747
|
if (!isPromiseLike(promise)) {
|
|
743
748
|
throw new MongoInvalidArgumentError(
|
|
@@ -747,16 +752,22 @@ export class ClientSession
|
|
|
747
752
|
|
|
748
753
|
result = await promise;
|
|
749
754
|
|
|
755
|
+
// 5. (cont.) Determine the current state of the ClientSession (continued below)
|
|
750
756
|
if (
|
|
751
757
|
this.transaction.state === TxnState.NO_TRANSACTION ||
|
|
752
758
|
this.transaction.state === TxnState.TRANSACTION_COMMITTED ||
|
|
753
759
|
this.transaction.state === TxnState.TRANSACTION_ABORTED
|
|
754
760
|
) {
|
|
755
|
-
//
|
|
761
|
+
// 7. If the ClientSession is in the "no transaction", "transaction aborted", or "transaction committed" state,
|
|
762
|
+
// assume the callback intentionally aborted or committed the transaction and return immediately.
|
|
756
763
|
return result;
|
|
757
764
|
}
|
|
765
|
+
// 5. (cont.) and whether the callback reported an error
|
|
766
|
+
// 6. If the callback reported an error:
|
|
758
767
|
} catch (fnError) {
|
|
759
768
|
if (!(fnError instanceof MongoError) || fnError instanceof MongoInvalidArgumentError) {
|
|
769
|
+
// This first preemptive abort regardless of TxnState isn't spec,
|
|
770
|
+
// and it's unclear whether it's serving a practical purpose, but this logic is OLD
|
|
760
771
|
await this.abortTransaction();
|
|
761
772
|
throw fnError;
|
|
762
773
|
}
|
|
@@ -765,6 +776,8 @@ export class ClientSession
|
|
|
765
776
|
this.transaction.state === TxnState.STARTING_TRANSACTION ||
|
|
766
777
|
this.transaction.state === TxnState.TRANSACTION_IN_PROGRESS
|
|
767
778
|
) {
|
|
779
|
+
// 6.i If the ClientSession is in the "starting transaction" or "transaction in progress" state,
|
|
780
|
+
// invoke abortTransaction on the session
|
|
768
781
|
await this.abortTransaction();
|
|
769
782
|
}
|
|
770
783
|
|
|
@@ -772,9 +785,15 @@ export class ClientSession
|
|
|
772
785
|
fnError.hasErrorLabel(MongoErrorLabel.TransientTransactionError) &&
|
|
773
786
|
(this.timeoutContext != null || processTimeMS() - startTime < MAX_TIMEOUT)
|
|
774
787
|
) {
|
|
788
|
+
// 6.ii If the callback's error includes a "TransientTransactionError" label and the elapsed time of `withTransaction`
|
|
789
|
+
// is less than 120 seconds, jump back to step two.
|
|
775
790
|
continue;
|
|
776
791
|
}
|
|
777
792
|
|
|
793
|
+
// 6.iii If the callback's error includes a "UnknownTransactionCommitResult" label, the callback must have manually committed a transaction,
|
|
794
|
+
// propagate the callback's error to the caller of withTransaction and return immediately.
|
|
795
|
+
// The 6.iii check is redundant with 6.iv, so we don't write code for it
|
|
796
|
+
// 6.iv Otherwise, propagate the callback's error to the caller of withTransaction and return immediately.
|
|
778
797
|
throw fnError;
|
|
779
798
|
}
|
|
780
799
|
|
|
@@ -785,8 +804,10 @@ export class ClientSession
|
|
|
785
804
|
* apply a majority write concern if commitTransaction is
|
|
786
805
|
* being retried (see: DRIVERS-601)
|
|
787
806
|
*/
|
|
807
|
+
// 8. Invoke commitTransaction on the session.
|
|
788
808
|
await this.commitTransaction();
|
|
789
809
|
committed = true;
|
|
810
|
+
// 9. If commitTransaction reported an error:
|
|
790
811
|
} catch (commitError) {
|
|
791
812
|
/*
|
|
792
813
|
* Note: a maxTimeMS error will have the MaxTimeMSExpired
|
|
@@ -800,6 +821,8 @@ export class ClientSession
|
|
|
800
821
|
commitError.hasErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult) &&
|
|
801
822
|
(this.timeoutContext != null || processTimeMS() - startTime < MAX_TIMEOUT)
|
|
802
823
|
) {
|
|
824
|
+
// 9.i If the `commitTransaction` error includes a "UnknownTransactionCommitResult" label and the error is not
|
|
825
|
+
// MaxTimeMSExpired and the elapsed time of `withTransaction` is less than 120 seconds, jump back to step eight.
|
|
803
826
|
continue;
|
|
804
827
|
}
|
|
805
828
|
|
|
@@ -807,9 +830,12 @@ export class ClientSession
|
|
|
807
830
|
commitError.hasErrorLabel(MongoErrorLabel.TransientTransactionError) &&
|
|
808
831
|
(this.timeoutContext != null || processTimeMS() - startTime < MAX_TIMEOUT)
|
|
809
832
|
) {
|
|
833
|
+
// 9.ii If the commitTransaction error includes a "TransientTransactionError" label
|
|
834
|
+
// and the elapsed time of withTransaction is less than 120 seconds, jump back to step two.
|
|
810
835
|
break;
|
|
811
836
|
}
|
|
812
837
|
|
|
838
|
+
// 9.iii Otherwise, propagate the commitTransaction error to the caller of withTransaction and return immediately.
|
|
813
839
|
throw commitError;
|
|
814
840
|
}
|
|
815
841
|
}
|