diff --git a/services/identity/src/database/one_time_keys.rs b/services/identity/src/database/one_time_keys.rs --- a/services/identity/src/database/one_time_keys.rs +++ b/services/identity/src/database/one_time_keys.rs @@ -68,17 +68,16 @@ // TODO: Introduce `transact_write_helper` similar to `batch_write_helper` // in `comm-lib` to handle transactions with retries - let mut attempt = 0; + let retry_config = ExponentialBackoffConfig { + max_attempts: retry::MAX_ATTEMPTS as u32, + ..Default::default() + }; // TODO: Introduce nanny task that handles calling `spawn_refresh_keys_task` let mut requested_more_keys = false; + let mut exponential_backoff = retry_config.new_counter(); loop { - attempt += 1; - if attempt > retry::MAX_ATTEMPTS { - return Err(Error::MaxRetriesExceeded); - } - let otk_count = self.get_otk_count(user_id, device_id, account_type).await?; if otk_count < ONE_TIME_KEY_MINIMUM_THRESHOLD && can_request_more_keys { @@ -149,6 +148,7 @@ ]); if is_transaction_retryable(&dynamo_db_error, &retryable_codes) { info!("Encountered transaction conflict while retrieving one-time key - retrying"); + exponential_backoff.sleep_and_retry().await?; } else { error!( errorType = error_types::OTK_DB_LOG, diff --git a/shared/comm-lib/src/database.rs b/shared/comm-lib/src/database.rs --- a/shared/comm-lib/src/database.rs +++ b/shared/comm-lib/src/database.rs @@ -484,7 +484,7 @@ } impl ExponentialBackoffConfig { - fn new_counter(&self) -> ExponentialBackoffHelper { + pub fn new_counter(&self) -> ExponentialBackoffHelper { ExponentialBackoffHelper::new(self) } fn backoff_enabled(&self) -> bool { @@ -690,8 +690,8 @@ Ok(()) } - /// internal helper struct - struct ExponentialBackoffHelper<'cfg> { + /// Utility for managing retries with exponential backoff + pub struct ExponentialBackoffHelper<'cfg> { config: &'cfg ExponentialBackoffConfig, attempt: u32, } @@ -702,12 +702,12 @@ } /// reset counter after successfull operation - fn reset(&mut self) { + pub fn reset(&mut self) { self.attempt = 0; } /// increase counter and sleep in case of failure - async fn sleep_and_retry(&mut self) -> Result<(), super::Error> { + pub async fn sleep_and_retry(&mut self) -> Result<(), super::Error> { let jitter_factor = 1f32.min(0f32.max(self.config.jitter_factor)); let random_multiplier = 1.0 + rand::thread_rng().gen_range(-jitter_factor..=jitter_factor);