summaryrefslogtreecommitdiffhomepage
path: root/android/src
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-09-30 12:19:51 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-09-30 12:19:51 -0300
commit125f6919c78785fa68bcad71ae40ad298ba719c1 (patch)
tree96128824215b49579ac4f017dda85718c4fc75e4 /android/src
parent351cb82b026f499e0dd7de2f848f08689dbbc034 (diff)
parent854e2c655747f74782f0361618c1974d8e3f3198 (diff)
downloadmullvadvpn-125f6919c78785fa68bcad71ae40ad298ba719c1.tar.xz
mullvadvpn-125f6919c78785fa68bcad71ae40ad298ba719c1.zip
Merge branch 'exponential-backoff-helper-class'
Diffstat (limited to 'android/src')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt35
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/LocationInfoCache.kt30
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/util/ExponentialBackoff.kt52
3 files changed, 76 insertions, 41 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt
index 55342ea166..cc13ec125a 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt
@@ -1,23 +1,23 @@
package net.mullvad.mullvadvpn.service
-import kotlin.math.min
import kotlinx.coroutines.delay
import net.mullvad.mullvadvpn.model.GetAccountDataResult
+import net.mullvad.mullvadvpn.util.ExponentialBackoff
import net.mullvad.mullvadvpn.util.JobTracker
import net.mullvad.talpid.util.EventNotifier
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
-// Number of retry attempts to check for a changed expiry before giving up.
-// Current value will force the cache to keep fetching for about four minutes or until a new expiry
-// value is received.
-// This is only used if the expiry was invalidated and fetching a new expiry returns the same value
-// as before the invalidation.
-const val MAX_INVALIDATED_RETRIES = 7
-
class AccountCache(val daemon: MullvadDaemon, val settingsListener: SettingsListener) {
companion object {
public val EXPIRY_FORMAT = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss z")
+
+ // Number of retry attempts to check for a changed expiry before giving up.
+ // Current value will force the cache to keep fetching for about four minutes or until a new
+ // expiry value is received.
+ // This is only used if the expiry was invalidated and fetching a new expiry returns the
+ // same value as before the invalidation.
+ private const val MAX_INVALIDATED_RETRIES = 7
}
val onAccountNumberChange = EventNotifier<String?>(null)
@@ -60,21 +60,25 @@ class AccountCache(val daemon: MullvadDaemon, val settingsListener: SettingsList
synchronized(this) {
accountNumber?.let { account ->
jobTracker.newBackgroundJob("fetch") {
- var retryAttempt = 0
+ val delays = ExponentialBackoff().apply {
+ cap = 2 /* h */ * 60 /* min */ * 60 /* s */ * 1000 /* ms */
+ }
do {
val result = daemon.getAccountData(account)
if (result is GetAccountDataResult.Ok) {
- if (handleNewExpiry(account, result.accountData.expiry, retryAttempt)) {
+ val expiry = result.accountData.expiry
+ val retryAttempt = delays.iteration
+
+ if (handleNewExpiry(account, expiry, retryAttempt)) {
break
}
} else if (result is GetAccountDataResult.InvalidAccount) {
break
}
- retryAttempt += 1
- delay(calculateRetryFetchDelay(retryAttempt))
+ delay(delays.next())
} while (onAccountExpiryChange.hasListeners())
}
}
@@ -153,11 +157,4 @@ class AccountCache(val daemon: MullvadDaemon, val settingsListener: SettingsList
return false
}
}
-
- private fun calculateRetryFetchDelay(retryAttempt: Int): Long {
- // delay in seconds = 2 ^ retryAttempt capped at 2^13 (8192)
- val exponent = min(retryAttempt, 13)
-
- return (1L shl exponent) * 1000L
- }
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/LocationInfoCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/LocationInfoCache.kt
index f679f11c1b..acfb93296b 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/LocationInfoCache.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/LocationInfoCache.kt
@@ -12,13 +12,10 @@ import net.mullvad.mullvadvpn.relaylist.Relay
import net.mullvad.mullvadvpn.relaylist.RelayCity
import net.mullvad.mullvadvpn.relaylist.RelayCountry
import net.mullvad.mullvadvpn.relaylist.RelayItem
+import net.mullvad.mullvadvpn.util.ExponentialBackoff
import net.mullvad.talpid.ConnectivityListener
import net.mullvad.talpid.tunnel.ActionAfterDisconnect
-const val DELAY_SCALE: Long = 50
-const val MAX_DELAY: Long = 30 * 60 * 1000
-const val MAX_RETRIES: Int = 17 // ceil(log2(MAX_DELAY / DELAY_SCALE) + 1)
-
class LocationInfoCache(
val daemon: MullvadDaemon,
val connectionProxy: ConnectionProxy,
@@ -142,15 +139,18 @@ class LocationInfoCache(
val previousFetch = activeFetch
activeFetch = GlobalScope.launch(Dispatchers.Main) {
+ val delays = ExponentialBackoff().apply {
+ scale = 50
+ cap = 30 /* min */ * 60 /* s */ * 1000 /* ms */
+ count = 17 // ceil(log2(cap / scale) + 1)
+ }
+
var newLocation: GeoIpLocation? = null
- var retry = 0
previousFetch?.join()
while (newLocation == null && fetchId == fetchIdCounter) {
- delayFetch(retry)
- retry += 1
-
+ delay(delays.next())
newLocation = executeFetch().await()
}
@@ -169,18 +169,4 @@ class LocationInfoCache(
private fun executeFetch() = GlobalScope.async(Dispatchers.Default) {
daemon.getCurrentLocation()
}
-
- private suspend fun delayFetch(retryAttempt: Int) {
- var duration = 0L
-
- // The first attempt has no delay
- if (retryAttempt >= MAX_RETRIES) {
- duration = MAX_DELAY
- } else if (retryAttempt >= 1) {
- val exponent = retryAttempt - 1
- duration = (1L shl exponent) * DELAY_SCALE
- }
-
- delay(duration)
- }
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/util/ExponentialBackoff.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/ExponentialBackoff.kt
new file mode 100644
index 0000000000..1117b0b749
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/ExponentialBackoff.kt
@@ -0,0 +1,52 @@
+package net.mullvad.mullvadvpn.util
+
+// Calculates a series of delays that increase exponentially.
+//
+// The delays follow the formula:
+//
+// (base ^ retryAttempt) * scale
+//
+// but it is never larger than the specified cap value.
+class ExponentialBackoff : Iterator<Long> {
+ private var unscaledValue = 1L
+ private var current = 1L
+
+ var iteration = 1
+ private set
+
+ var base = 2L
+ var scale = 1000L
+ var cap = Long.MAX_VALUE
+ var count: Int? = null
+
+ override fun hasNext(): Boolean {
+ val maxIterations = count
+
+ if (maxIterations != null) {
+ return iteration < maxIterations
+ } else {
+ return true
+ }
+ }
+
+ override fun next(): Long {
+ iteration += 1
+
+ if (current >= cap) {
+ return cap
+ } else {
+ val value = current
+
+ unscaledValue *= base
+ current = Math.min(cap, scale * unscaledValue)
+
+ return value
+ }
+ }
+
+ fun reset() {
+ unscaledValue = 1L
+ current = 1L
+ iteration = 1
+ }
+}