Loading app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +16 −2 Original line number Diff line number Diff line Loading @@ -51,7 +51,9 @@ import foundation.e.apps.data.playstore.utils.GPlayHttpClient import foundation.e.apps.data.playstore.utils.GplayHttpRequestException import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.di.qualifiers.IoCoroutineScope import foundation.e.apps.domain.entities.HttpUnauthorizedException import foundation.e.apps.utils.SystemInfoProvider import foundation.e.apps.utils.exponentialBackoffRetry import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading @@ -67,6 +69,7 @@ import java.util.Properties import javax.inject.Inject import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds import com.aurora.gplayapi.data.models.App as GplayApp @Suppress("TooManyFunctions", "LongParameterList") Loading Loading @@ -406,15 +409,26 @@ class PlayStoreRepository @Inject constructor( } private suspend fun <T> doAuthenticatedRequest(request: suspend (AuthData) -> T): T { return exponentialBackoffRetry( initialDelay = 100.milliseconds, maxDelay = 15.seconds, // exp: 0,2, 0,4, 0,8, 1,6, 3,2, 6,4 ; 12,8 . work = { gPlayRequestWithUnswallowedException { request(appLoungeDataStore.getAuthData()) } }, predicate = { exception -> exception is HttpUnauthorizedException }, doBeforeRetry = { refreshPlayStoreAuthentication() } ) } private suspend fun <T> gPlayRequestWithUnswallowedException(request: suspend () -> T): T { val lastErrorFlow = gPlayHttpClient.requestException.shareIn( scope = ioCoroutineScope, started = SharingStarted.Eagerly, replay = 1 ) val authData = appLoungeDataStore.getAuthData() return try { request(authData) request() } catch(e: Exception) { lastErrorFlow.timeout(gPlayHttpClientPukedExceptionWaitDuration) .catch { Loading app/src/main/java/foundation/e/apps/data/playstore/utils/GPlayHttpClient.kt +1 −1 Original line number Diff line number Diff line Loading @@ -205,7 +205,7 @@ class GPlayHttpClient @Inject constructor( } ioCoroutineScope.launch { rawErrorResponse.emit(parsedException) _requestException.emit(parsedException) } // Swallow the exception, until upper layer are upgraded. Loading app/src/main/java/foundation/e/apps/utils/ExponentialBackoffRetry.kt 0 → 100644 +30 −0 Original line number Diff line number Diff line package foundation.e.apps.utils import kotlinx.coroutines.delay import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds suspend fun <T> exponentialBackoffRetry( initialDelay: Duration = 100.milliseconds, maxDelay: Duration = 15.seconds, work: suspend () -> T, predicate: suspend (Throwable) -> Boolean = { true }, doBeforeRetry: suspend () -> Unit = {} ): T { var d = initialDelay while (true) { try { if (d > initialDelay) { doBeforeRetry() } return work() } catch (exception: Exception) { d = d * 2 if (predicate(exception) && d <= maxDelay) { delay(d) } throw exception } } } Loading
app/src/main/java/foundation/e/apps/data/playstore/PlayStoreRepository.kt +16 −2 Original line number Diff line number Diff line Loading @@ -51,7 +51,9 @@ import foundation.e.apps.data.playstore.utils.GPlayHttpClient import foundation.e.apps.data.playstore.utils.GplayHttpRequestException import foundation.e.apps.data.preference.AppLoungeDataStore import foundation.e.apps.di.qualifiers.IoCoroutineScope import foundation.e.apps.domain.entities.HttpUnauthorizedException import foundation.e.apps.utils.SystemInfoProvider import foundation.e.apps.utils.exponentialBackoffRetry import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading @@ -67,6 +69,7 @@ import java.util.Properties import javax.inject.Inject import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds import com.aurora.gplayapi.data.models.App as GplayApp @Suppress("TooManyFunctions", "LongParameterList") Loading Loading @@ -406,15 +409,26 @@ class PlayStoreRepository @Inject constructor( } private suspend fun <T> doAuthenticatedRequest(request: suspend (AuthData) -> T): T { return exponentialBackoffRetry( initialDelay = 100.milliseconds, maxDelay = 15.seconds, // exp: 0,2, 0,4, 0,8, 1,6, 3,2, 6,4 ; 12,8 . work = { gPlayRequestWithUnswallowedException { request(appLoungeDataStore.getAuthData()) } }, predicate = { exception -> exception is HttpUnauthorizedException }, doBeforeRetry = { refreshPlayStoreAuthentication() } ) } private suspend fun <T> gPlayRequestWithUnswallowedException(request: suspend () -> T): T { val lastErrorFlow = gPlayHttpClient.requestException.shareIn( scope = ioCoroutineScope, started = SharingStarted.Eagerly, replay = 1 ) val authData = appLoungeDataStore.getAuthData() return try { request(authData) request() } catch(e: Exception) { lastErrorFlow.timeout(gPlayHttpClientPukedExceptionWaitDuration) .catch { Loading
app/src/main/java/foundation/e/apps/data/playstore/utils/GPlayHttpClient.kt +1 −1 Original line number Diff line number Diff line Loading @@ -205,7 +205,7 @@ class GPlayHttpClient @Inject constructor( } ioCoroutineScope.launch { rawErrorResponse.emit(parsedException) _requestException.emit(parsedException) } // Swallow the exception, until upper layer are upgraded. Loading
app/src/main/java/foundation/e/apps/utils/ExponentialBackoffRetry.kt 0 → 100644 +30 −0 Original line number Diff line number Diff line package foundation.e.apps.utils import kotlinx.coroutines.delay import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds suspend fun <T> exponentialBackoffRetry( initialDelay: Duration = 100.milliseconds, maxDelay: Duration = 15.seconds, work: suspend () -> T, predicate: suspend (Throwable) -> Boolean = { true }, doBeforeRetry: suspend () -> Unit = {} ): T { var d = initialDelay while (true) { try { if (d > initialDelay) { doBeforeRetry() } return work() } catch (exception: Exception) { d = d * 2 if (predicate(exception) && d <= maxDelay) { delay(d) } throw exception } } }