Skip to content

Instantly share code, notes, and snippets.

@xmaihh
Created March 31, 2023 07:20
Show Gist options
  • Save xmaihh/a3314957bb613485164c6ed91f4b9d08 to your computer and use it in GitHub Desktop.
Save xmaihh/a3314957bb613485164c6ed91f4b9d08 to your computer and use it in GitHub Desktop.
Kotlin执行指定的异步任务,并在规定时间内尝试重发直到满足条件或者超时
/**
* 执行指定的异步任务,并在规定时间内尝试重发直到满足条件或者超时。
*
* @param timeout 超时时间,单位为毫秒。
* @param retryCount 最多重发次数。
* @param delayTime 重发间隔时间,单位为毫秒。
* @param shouldRetryPredicate 判断是否需要进行重发的函数。该函数返回true时进行重发。
* @param block 异步任务的执行体。该执行体需要支持取消操作。
* @return 异步任务的返回结果,如果超时或者达到最大重发次数仍未获取到期望结果,则返回null。
*/
private suspend fun <T> withRetryAndWaitForResult(
timeout: Long,
retryCount: Int,
delayTime: Long = 0L,
shouldRetryPredicate: suspend (result: T?) -> Boolean,
block: suspend () -> T
): T? = supervisorScope {
var retry = 0
var result: T? = null
while (shouldRetry) {
// 设置超时时间
val timeoutResult = withTimeoutOrNull(timeout) {
// 执行异步任务
block()
}
// 判断是否超时
if (timeoutResult == null) {
retry++
//判断是否达到最大重发次数
if (retry >= retryCount) {
break
}
//等待一段时间后重发
if (delayTime > 0) {
delay(delayTime)
}
} else {
result = timeoutResult
// 判断是否需要进行重发
if (!shouldRetryPredicate(result)) {
break // 不需要重发,直接返回结果
}
//如果不满足停止条件,则继续重发
retry++
if (retry >= retryCount) {
break
}
//等待一段时间后重发
if (delayTime > 0) {
delay(delayTime)
}
}
}
result
}
fun main() = runBlocking {
var shouldRetry = true // 外部变量,用于控制是否重发
// 执行异步任务,并设置超时时间为5秒。
val result = withTimeoutAndConditionalRetryAndWaitForResult<String>(timeout = 1500, retryCount = 3, delayTime = 1000, { stopCondition(it) }) {
if (shouldRetry) { // 检查外部变量是否改变
doTask()
} else {
null // 如果外部变量已经改变,则直接返回null
}
}
// 输出结果
println(result ?: "Timeout or should not retry.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment