Respect 429 in SVR write requests.

This commit is contained in:
Greyson Parrelli
2026-01-07 12:23:55 -05:00
committed by jeffrey-signal
parent e3b569ca5b
commit 4b41989b30
7 changed files with 39 additions and 10 deletions

View File

@@ -9,6 +9,7 @@ import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.Job.Result
import org.thoughtcrime.securesms.jobmanager.JsonJobData
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -20,6 +21,7 @@ import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSes
import org.whispersystems.signalservice.internal.push.AuthCredentials
import kotlin.concurrent.withLock
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
/**
* Attempts to reset the guess on the SVR PIN. Intended to be enqueued after a successful restore.
@@ -163,6 +165,11 @@ class ResetSvrGuessCountJob private constructor(
Log.w(TAG, "Failed to expose the backup. Giving up. $svr")
Result.success()
}
is BackupResponse.RateLimited -> {
val backoff = response.retryAfter ?: defaultBackoff().milliseconds
Log.w(TAG, "Hit rate limit. Retrying in $backoff")
Result.retry(backoff.inWholeMilliseconds)
}
is BackupResponse.NetworkError -> {
Log.w(TAG, "Hit a network error. Retrying. $svr", response.exception)
Result.retry(defaultBackoff())

View File

@@ -19,6 +19,7 @@ import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSes
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2
import kotlin.concurrent.withLock
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
/**
* Ensures a user's SVR data is written to SVR2.
@@ -109,6 +110,11 @@ class Svr2MirrorJob private constructor(parameters: Parameters, private var seri
Log.w(TAG, "Failed to expose the backup. Giving up.")
Result.success()
}
is BackupResponse.RateLimited -> {
val backoff = response.retryAfter ?: defaultBackoff().milliseconds
Log.w(TAG, "Hit rate limit. Retrying in $backoff")
Result.retry(backoff.inWholeMilliseconds)
}
is BackupResponse.NetworkError -> {
Log.w(TAG, "Hit a network error. Retrying.", response.exception)
Result.retry(defaultBackoff())

View File

@@ -18,6 +18,7 @@ import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSes
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV3
import kotlin.concurrent.withLock
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
/**
* Ensures a user's SVR data is written to SVR3.
@@ -93,6 +94,11 @@ class Svr3MirrorJob private constructor(parameters: Parameters, private var seri
Result.retry(defaultBackoff())
}
}
is BackupResponse.RateLimited -> {
val backoff = response.retryAfter ?: defaultBackoff().milliseconds
Log.w(TAG, "Hit rate limit. Retrying in $backoff")
Result.retry(backoff.inWholeMilliseconds)
}
BackupResponse.EnclaveNotFound -> {
Log.w(TAG, "Could not find the enclave. Giving up.")
Result.success()

View File

@@ -257,6 +257,7 @@ object SvrRepository {
BackupResponse.ExposeFailure -> it
is BackupResponse.NetworkError -> it
BackupResponse.ServerRejected -> it
is BackupResponse.RateLimited -> it
BackupResponse.EnclaveNotFound -> null
is BackupResponse.Success -> null
}