@@ -735,8 +735,35 @@ export class ClientSession
735735 let committed = false ;
736736 let result : T ;
737737
738+ let lastError : Error | null = null ;
739+
738740 try {
739- for ( let retry = 0 ; ! committed ; ++ retry ) {
741+ retryTransaction: for ( let attempt = 0 , isRetry = attempt > 0 ; ! committed ; ++ attempt ) {
742+ if ( isRetry ) {
743+ const BACKOFF_INITIAL_MS = 5 ;
744+ const BACKOFF_MAX_MS = 500 ;
745+ const BACKOFF_GROWTH = 1.5 ;
746+ const jitter = Math . random ( ) ;
747+ const backoffMS =
748+ jitter * Math . min ( BACKOFF_INITIAL_MS * BACKOFF_GROWTH ** attempt , BACKOFF_MAX_MS ) ;
749+
750+ const willExceedTransactionDeadline =
751+ ( this . timeoutContext ?. csotEnabled ( ) &&
752+ backoffMS > this . timeoutContext . remainingTimeMS ) ||
753+ processTimeMS ( ) + backoffMS > startTime + MAX_TIMEOUT ;
754+
755+ if ( willExceedTransactionDeadline ) {
756+ throw (
757+ lastError ??
758+ new MongoRuntimeError (
759+ `Transaction retry did not record an error: should never occur. Please file a bug.`
760+ )
761+ ) ;
762+ }
763+
764+ await setTimeout ( backoffMS ) ;
765+ }
766+
740767 this . startTransaction ( options ) ; // may throw on error
741768
742769 try {
@@ -774,13 +801,14 @@ export class ClientSession
774801 fnError . hasErrorLabel ( MongoErrorLabel . TransientTransactionError ) &&
775802 ( this . timeoutContext ?. csotEnabled ( ) || processTimeMS ( ) - startTime < MAX_TIMEOUT )
776803 ) {
777- continue ;
804+ lastError = fnError ;
805+ continue retryTransaction;
778806 }
779807
780808 throw fnError ;
781809 }
782810
783- while ( ! committed ) {
811+ retryCommit: while ( ! committed ) {
784812 try {
785813 /*
786814 * We will rely on ClientSession.commitTransaction() to
@@ -809,29 +837,13 @@ export class ClientSession
809837 * { ok:0, code: 50, codeName: 'MaxTimeMSExpired' }
810838 * { ok:1, writeConcernError: { code: 50, codeName: 'MaxTimeMSExpired' } }
811839 */
812- continue ;
840+ continue retryCommit ;
813841 }
814842
815843 if ( commitError . hasErrorLabel ( MongoErrorLabel . TransientTransactionError ) ) {
816- const BACKOFF_INITIAL_MS = 5 ;
817- const BACKOFF_MAX_MS = 500 ;
818- const BACKOFF_GROWTH = 1.5 ;
819- const jitter = Math . random ( ) ;
820- const backoffMS =
821- jitter * Math . min ( BACKOFF_INITIAL_MS * BACKOFF_GROWTH ** retry , BACKOFF_MAX_MS ) ;
822-
823- const willExceedTransactionDeadline =
824- ( this . timeoutContext ?. csotEnabled ( ) &&
825- backoffMS > this . timeoutContext . remainingTimeMS ) ||
826- processTimeMS ( ) + backoffMS > startTime + MAX_TIMEOUT ;
827-
828- if ( willExceedTransactionDeadline ) {
829- break ;
830- }
831-
832- await setTimeout ( backoffMS ) ;
844+ lastError = commitError ;
833845
834- break ;
846+ continue retryTransaction ;
835847 }
836848 }
837849
0 commit comments