@@ -37,7 +37,7 @@ import {
3737 supportsRetryableWrites
3838} from '../utils' ;
3939import { AggregateOperation } from './aggregate' ;
40- import { AbstractOperation , Aspect } from './operation' ;
40+ import { AbstractOperation , Aspect , RetryContext } from './operation' ;
4141
4242const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES . IllegalOperation ;
4343const MMAPv1_RETRY_WRITES_ERROR_MESSAGE =
@@ -254,18 +254,9 @@ async function executeOperationWithRetries<
254254 2 // backoff rate
255255 ) ;
256256
257- let maxAttempts =
258- ( operation . maxAttempts ?? willRetry ) ? ( timeoutContext . csotEnabled ( ) ? Infinity : 2 ) : 1 ;
259-
260- for (
261- let attempt = 0 ;
262- attempt < maxAttempts ;
263- attempt ++ ,
264- maxAttempts =
265- willRetry && previousOperationError ?. hasErrorLabel ( MongoErrorLabel . SystemOverloadedError )
266- ? 6
267- : maxAttempts
268- ) {
257+ const retryContext = new RetryContext ( willRetry , timeoutContext . csotEnabled ( ) ? Infinity : 2 ) ;
258+
259+ for ( ; retryContext . shouldRetry ( ) ; retryContext . recordFailure ( previousOperationError ) ) {
269260 if ( previousOperationError ) {
270261 if ( hasWriteAspect && previousOperationError . code === MMAPv1_RETRY_WRITES_ERROR_CODE ) {
271262 throw new MongoServerError ( {
@@ -294,7 +285,6 @@ async function executeOperationWithRetries<
294285
295286 // if the delay would exhaust the CSOT timeout, short-circuit.
296287 if ( timeoutContext . csotEnabled ( ) && delayMS > timeoutContext . remainingTimeMS ) {
297- // TODO: is this the right error to throw?
298288 throw new MongoOperationTimeoutError (
299289 `MongoDB SystemOverload exponential backoff would exceed timeoutMS deadline: remaining CSOT deadline=${ timeoutContext . remainingTimeMS } , backoff delayMS=${ delayMS } ` ,
300290 {
@@ -337,17 +327,15 @@ async function executeOperationWithRetries<
337327 operation . server = server ;
338328
339329 try {
340- const isRetry = attempt > 0 ;
341-
342330 // If attempt > 0 and we are command batching we need to reset the batch.
343- if ( isRetry && operation . hasAspect ( Aspect . COMMAND_BATCHING ) ) {
331+ if ( retryContext . isRetry && operation . hasAspect ( Aspect . COMMAND_BATCHING ) ) {
344332 operation . resetBatch ( ) ;
345333 }
346334
347335 try {
348336 const result = await server . command ( operation , timeoutContext ) ;
349337 topology . tokenBucket . deposit (
350- isRetry
338+ retryContext . isRetry
351339 ? // on successful retry, deposit the retry cost + the refresh rate.
352340 TOKEN_REFRESH_RATE + RETRY_COST
353341 : // otherwise, just deposit the refresh rate.
0 commit comments