-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
249cec7
commit 2041c5d
Showing
17 changed files
with
613 additions
and
73 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
...g-runtime/src/commonMain/kotlin/org/mobilenativefoundation/storex/paging/runtime/Pager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
package org.mobilenativefoundation.storex.paging.runtime | ||
|
||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.StateFlow | ||
|
||
interface Pager<Id: Identifier<Id>> { | ||
val flow: Flow<PagingState<Id>> | ||
val state: StateFlow<PagingState<Id>> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
...untime/src/commonMain/kotlin/org/mobilenativefoundation/storex/paging/runtime/Severity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.mobilenativefoundation.storex.paging.runtime | ||
|
||
enum class Severity { | ||
None, | ||
Error, | ||
Debug, | ||
Verbose | ||
} |
2 changes: 2 additions & 0 deletions
2
...tlin/org/mobilenativefoundation/storex/paging/runtime/internal/logger/api/PagingLogger.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
package org.mobilenativefoundation.storex.paging.runtime.internal.logger.api | ||
|
||
interface PagingLogger { | ||
fun verbose(message: String) | ||
fun debug(message: String) | ||
fun error(message: String, error: Throwable) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
...org/mobilenativefoundation/storex/paging/runtime/internal/pager/api/ExponentialBackoff.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.mobilenativefoundation.storex.paging.runtime.internal.pager.api | ||
|
||
import org.mobilenativefoundation.storex.paging.runtime.internal.pager.impl.DefaultExponentialBackoff | ||
import kotlin.time.Duration.Companion.minutes | ||
|
||
/** | ||
* Defines the contract for implementing an exponential backoff algorithm. | ||
* | ||
* This interface provides methods for calculating and executing delays | ||
* between retry attempts, typically increasing the delay exponentially | ||
* with each attempt to reduce system load during error conditions. | ||
*/ | ||
interface ExponentialBackoff { | ||
|
||
/** | ||
* Executes a given suspend function after applying the calculated delay. | ||
* | ||
* @param retryCount The current retry attempt number (0-based). | ||
* @param block The suspend function to be executed after the delay. | ||
*/ | ||
suspend fun execute(retryCount: Int, block: suspend () -> Unit) | ||
|
||
companion object { | ||
/** | ||
* Creates a default implementation of ExponentialBackoff. | ||
* | ||
* @param initialDelayMs The initial delay in milliseconds before the first retry. | ||
* @param maxDelayMs The maximum delay in milliseconds, capping the exponential growth. | ||
* @param multiplier The factor by which the delay increases with each retry. | ||
* @param jitterFactor The maximum proportion of the delay to be added or subtracted randomly. | ||
* @return An instance of ExponentialBackoff with the specified parameters. | ||
*/ | ||
fun default( | ||
initialDelayMs: Long = 100, | ||
maxDelayMs: Long = 1.minutes.inWholeMilliseconds, | ||
multiplier: Double = 2.0, | ||
jitterFactor: Double = 0.1 | ||
): ExponentialBackoff = DefaultExponentialBackoff(initialDelayMs, maxDelayMs, multiplier, jitterFactor) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
...in/org/mobilenativefoundation/storex/paging/runtime/internal/pager/api/RetryBookkeeper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.mobilenativefoundation.storex.paging.runtime.internal.pager.api | ||
|
||
import org.mobilenativefoundation.storex.paging.runtime.Identifier | ||
import org.mobilenativefoundation.storex.paging.runtime.PagingSource | ||
|
||
interface RetryBookkeeper<Id : Identifier<Id>, K : Comparable<K>> { | ||
suspend fun getCount(params: PagingSource.LoadParams<K>): Int | ||
suspend fun incrementCount(params: PagingSource.LoadParams<K>) | ||
suspend fun resetCount(params: PagingSource.LoadParams<K>) | ||
} |
62 changes: 62 additions & 0 deletions
62
...lenativefoundation/storex/paging/runtime/internal/pager/impl/DefaultExponentialBackoff.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package org.mobilenativefoundation.storex.paging.runtime.internal.pager.impl | ||
|
||
import kotlinx.coroutines.delay | ||
import org.mobilenativefoundation.storex.paging.runtime.internal.pager.api.ExponentialBackoff | ||
import kotlin.math.min | ||
import kotlin.math.pow | ||
import kotlin.random.Random | ||
|
||
/** | ||
* Default implementation of the [ExponentialBackoff] interface. | ||
* | ||
* This class implements an exponential backoff algorithm with jitter for retry mechanisms. | ||
* It calculates delays between retry attempts, increasing the delay exponentially with each | ||
* attempt and adding a random jitter to prevent synchronized retries from multiple clients. | ||
* | ||
* @property initialDelayMs The initial delay in milliseconds before the first retry. | ||
* @property maxDelayMs The maximum delay in milliseconds, capping the exponential growth. | ||
* @property multiplier The factor by which the delay increases with each retry. | ||
* @property jitterFactor The maximum proportion of the delay to be added or subtracted randomly. | ||
*/ | ||
class DefaultExponentialBackoff( | ||
private val initialDelayMs: Long, | ||
private val maxDelayMs: Long, | ||
private val multiplier: Double, | ||
private val jitterFactor: Double | ||
) : ExponentialBackoff { | ||
/** | ||
* Executes a given suspend function after applying the calculated delay. | ||
* | ||
* @param retryCount The current retry attempt number. | ||
* @param block The suspend function to be executed after the delay. | ||
*/ | ||
override suspend fun execute(retryCount: Int, block: suspend () -> Unit) { | ||
val delayMs = calculateDelay(retryCount) | ||
delay(delayMs) | ||
block() | ||
} | ||
|
||
/** | ||
* Calculates the delay for a given retry attempt. | ||
* | ||
* The delay is calculated using the formula: | ||
* delay = min(initialDelay * (multiplier ^ retryCount), maxDelay) + jitter | ||
* | ||
* @param retryCount The current retry attempt number. | ||
* @return The calculated delay in milliseconds. | ||
*/ | ||
private fun calculateDelay(retryCount: Int): Long { | ||
// Calculate the base delay using exponential backoff | ||
val baseDelay = (initialDelayMs * multiplier.pow(retryCount.toDouble())).toLong() | ||
|
||
// Cap the delay at the maximum allowed delay | ||
val maxDelayBeforeJitter = min(baseDelay, maxDelayMs) | ||
|
||
// Calculate jitter as a random value between -jitterFactor and +jitterFactor of the delay | ||
val jitter = (Random.nextDouble() * 2 - 1) * jitterFactor * maxDelayBeforeJitter | ||
|
||
// Add jitter to the delay and ensure it's not negative | ||
return (maxDelayBeforeJitter + jitter).toLong().coerceAtLeast(0L) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.