Skip to content

Commit f2db7df

Browse files
committed
feat(auth): add exponential backoff with jitter on token refresh failures (fixes #1629)
1 parent 490587b commit f2db7df

2 files changed

Lines changed: 19 additions & 6 deletions

File tree

‎auth/src/desktop/auth_desktop.cc‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,8 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) {
681681
thread_ = firebase::Thread(
682682
[](IdTokenRefreshThread* refresh_thread) {
683683
Auth* auth = refresh_thread->auth;
684+
int retry_backoff_ms = kMinRetryBackoffMs;
685+
684686
while (!refresh_thread->is_shutting_down()) {
685687
// Note: Make sure to always make future_impl.mutex the innermost
686688
// lock, to prevent deadlocks!
@@ -714,10 +716,20 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) {
714716
// is completed.
715717
future_sem.Wait();
716718

717-
// If token refresh failed (e.g. network outage), wait before retrying
718-
// to prevent a 0ms tight retry loop and high CPU usage.
719-
if (future.error() != 0 && !refresh_thread->is_shutting_down()) {
720-
refresh_thread->wakeup_sem_.TimedWait(kMsPerTokenRefreshFailedRetry);
719+
if (future.error() != 0) {
720+
// Token refresh failed (e.g. network outage). Wait with exponential backoff
721+
// to prevent tight retry loops and avoid overloading backend servers upon reconnect.
722+
if (!refresh_thread->is_shutting_down()) {
723+
int jitter_ms = rand() % 1000;
724+
int wait_time_ms = retry_backoff_ms + jitter_ms;
725+
// Double backoff for consecutive failures up to max 30 minutes.
726+
retry_backoff_ms = std::min(kMaxRetryBackoffMs, retry_backoff_ms * 2);
727+
refresh_thread->wakeup_sem_.TimedWait(wait_time_ms);
728+
}
729+
continue;
730+
} else {
731+
// Refresh succeeded! Reset backoff to minimum interval.
732+
retry_backoff_ms = kMinRetryBackoffMs;
721733
}
722734
} else {
723735
auth->auth_data_->future_impl.mutex().Release();

‎auth/src/desktop/auth_desktop.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ struct AuthImpl {
179179
const int kMinutesPerTokenRefresh = 58;
180180
const int kMsPerTokenRefresh =
181181
kMinutesPerTokenRefresh * internal::kMillisecondsPerMinute;
182-
// Retry delay when token refresh fails (e.g., due to network outage).
183-
const int kMsPerTokenRefreshFailedRetry = 30 * 1000;
182+
// Exponential backoff parameters when token refresh fails (e.g. network outage).
183+
const int kMinRetryBackoffMs = 30 * 1000; // 30 seconds base delay
184+
const int kMaxRetryBackoffMs = 30 * 60 * 1000; // 30 minutes max delay
184185

185186
void InitializeUserDataPersist(AuthData* auth_data);
186187
void DestroyUserDataPersist(AuthData* auth_data);

0 commit comments

Comments
 (0)