@@ -247,7 +247,7 @@ synchronized void clearRateLimitState() {
247247 synchronized boolean isRateLimited () {
248248 if (!rateLimited ) return false ;
249249 if (System .currentTimeMillis () >= rateLimitWaitUntil ) {
250- rateLimited = false ;
250+ clearRateLimitState () ;
251251 return false ;
252252 }
253253 return true ;
@@ -646,13 +646,19 @@ public void run() {
646646
647647 // Sleep for Retry-After then retry this batch
648648 if (result .retryAfterSeconds > 0 ) {
649+ // Defensive guard: if backoff retries have already been exhausted,
650+ // do not continue looping in the Retry-After path.
651+ if (backoffAttempts >= maxBackoffAttempts ) {
652+ break ;
653+ }
649654 try {
650655 TimeUnit .SECONDS .sleep (result .retryAfterSeconds );
651656 } catch (InterruptedException e ) {
652657 client .log .print (
653658 DEBUG ,
654659 "Thread interrupted while waiting for Retry-After for batch %s." ,
655660 batch .sequence ());
661+ client .clearRateLimitState ();
656662 Thread .currentThread ().interrupt ();
657663 return ;
658664 }
@@ -667,6 +673,7 @@ public void run() {
667673 } catch (InterruptedException e ) {
668674 client .log .print (
669675 DEBUG , "Thread interrupted while backing off for batch %s." , batch .sequence ());
676+ client .clearRateLimitState ();
670677 Thread .currentThread ().interrupt ();
671678 return ;
672679 }
@@ -691,11 +698,13 @@ public void run() {
691698 } catch (InterruptedException e ) {
692699 client .log .print (
693700 DEBUG , "Thread interrupted while backing off for batch %s." , batch .sequence ());
701+ client .clearRateLimitState ();
694702 Thread .currentThread ().interrupt ();
695703 return ;
696704 }
697705 }
698706
707+ client .clearRateLimitState ();
699708 client .log .print (ERROR , "Could not upload batch %s. Retries exhausted." , batch .sequence ());
700709 notifyCallbacksWithException (
701710 batch , new IOException (Integer .toString (totalAttempts ) + " retries exhausted" ));
0 commit comments