@@ -30,7 +30,12 @@ import type { Topology } from '../sdam/topology';
3030import type { ClientSession } from '../sessions' ;
3131import { TimeoutContext } from '../timeout' ;
3232import { RETRY_COST , TOKEN_REFRESH_RATE } from '../token_bucket' ;
33- import { abortable , maxWireVersion , supportsRetryableWrites } from '../utils' ;
33+ import {
34+ abortable ,
35+ exponentialBackoffDelayProvider ,
36+ maxWireVersion ,
37+ supportsRetryableWrites
38+ } from '../utils' ;
3439import { AggregateOperation } from './aggregate' ;
3540import { AbstractOperation , Aspect } from './operation' ;
3641
@@ -245,14 +250,28 @@ async function tryOperation<T extends AbstractOperation, TResult = ResultTypeFro
245250
246251 let systemOverloadRetryAttempt = 0 ;
247252 const maxSystemOverloadRetryAttempts = 5 ;
253+ const backoffDelayProvider = exponentialBackoffDelayProvider (
254+ 10_000 , // MAX_BACKOFF
255+ 100 , // base backoff
256+ 2 // backoff rate
257+ ) ;
248258
249259 while ( true ) {
250260 if ( previousOperationError ) {
251261 if ( previousOperationError . hasErrorLabel ( MongoErrorLabel . SystemOverloadError ) ) {
252262 systemOverloadRetryAttempt += 1 ;
253263
254- // if the SystemOverloadError is not retryable, throw.
255- if ( ! previousOperationError . hasErrorLabel ( MongoErrorLabel . RetryableError ) ) {
264+ if (
265+ // if the SystemOverloadError is not retryable, throw.
266+ ! previousOperationError . hasErrorLabel ( MongoErrorLabel . RetryableError ) ||
267+ ! (
268+ // if retryable writes or reads are not configured, throw.
269+ (
270+ ( hasReadAspect && topology . s . options . retryReads ) ||
271+ ( hasWriteAspect && topology . s . options . retryWrites )
272+ )
273+ )
274+ ) {
256275 throw previousOperationError ;
257276 }
258277
@@ -261,12 +280,7 @@ async function tryOperation<T extends AbstractOperation, TResult = ResultTypeFro
261280 throw previousOperationError ;
262281 }
263282
264- const delayMS =
265- Math . random ( ) *
266- Math . min (
267- 10_000 , // MAX_BACKOFF,
268- 100 * 2 ** systemOverloadRetryAttempt
269- ) ;
283+ const { value : delayMS } = backoffDelayProvider . next ( ) ;
270284
271285 // if the delay would exhaust the CSOT timeout, short-circuit.
272286 if ( timeoutContext . csotEnabled ( ) && delayMS > timeoutContext . remainingTimeMS ) {
0 commit comments