• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

michaelbull/kotlin-retry: A higher-order function for retrying operations that m ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

michaelbull/kotlin-retry

开源软件地址(OpenSource Url):

https://github.com/michaelbull/kotlin-retry

开源编程语言(OpenSource Language):

Kotlin 100.0%

开源软件介绍(OpenSource Introduction):

kotlin-retry

Maven Central CI Status License

retry is a higher-order function for retrying operations that may fail.

retry(limitAttempts(10) + constantDelay(delayMillis = 50L)) {
    /* your code */
}

Installation

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.michael-bull.kotlin-retry:kotlin-retry:1.0.9")
}

Introduction

IO operations often experience temporary failures that warrant re-execution, e.g. a database transaction that may fail due to a deadlock.12

“even if your application logic is correct, you must still handle the case where a transaction must be retried”

Deadlocks in InnoDB

The retry function simplifies this process by wrapping the application logic and applying a specified RetryPolicy.

In the example below, either of the calls to customers.nameFromId may fail, abandoning the remaining logic within the printExchangeBetween function. As such, we may want to retry this operation until 5 attempts in total have been executed:

import com.github.michaelbull.retry.policy.limitAttempts
import com.github.michaelbull.retry.retry
import kotlinx.coroutines.runBlocking

suspend fun printExchangeBetween(a: Long, b: Long) {
    val customer1 = customers.nameFromId(a)
    val customer2 = customers.nameFromId(b)
    println("$customer1 exchanged with $customer2")
}

fun main() = runBlocking {
    retry(limitAttempts(5)) {
        printExchangeBetween(1L, 2L)
    }
}

We can also provide a RetryPolicy that only retries failures of a specific type. The example below will retry the operation only if the reason for failure was a SQLDataException, pausing for 20 milliseconds before retrying and stopping after 5 total attempts.

import com.github.michaelbull.retry.ContinueRetrying
import com.github.michaelbull.retry.StopRetrying
import com.github.michaelbull.retry.policy.RetryPolicy
import com.github.michaelbull.retry.policy.constantDelay
import com.github.michaelbull.retry.policy.limitAttempts
import com.github.michaelbull.retry.policy.plus
import com.github.michaelbull.retry.retry
import kotlinx.coroutines.runBlocking
import java.sql.SQLDataException

val retryTimeouts: RetryPolicy<Throwable> = {
    if (reason is SQLDataException) ContinueRetrying else StopRetrying
}

suspend fun printExchangeBetween(a: Long, b: Long) {
    val customer1 = customers.nameFromId(a)
    val customer2 = customers.nameFromId(b)
    println("$customer1 exchanged with $customer2")
}

fun main() = runBlocking {
    retry(retryTimeouts + limitAttempts(5) + constantDelay(20)) {
        printExchangeBetween(1L, 2L)
    }
}

Backoff

The examples above retry executions immediately after they fail, however we may wish to spread out retries with an ever-increasing delay. This is known as a "backoff" and comes in many forms. This library includes all the forms of backoff strategy detailed the article by Marc Brooker on the AWS Architecture Blog entitled "Exponential Backoff And Jitter".

Binary Exponential

“exponential backoff means that clients multiply their backoff by a constant after each attempt, up to some maximum value”

sleep = min(cap, base * 2 ** attempt)
retry(limitAttempts(5) + binaryExponentialBackoff(base = 10L, max = 5000L)) {
    /* code */
}

Full Jitter

“trying to improve the performance of a system by adding randomness ... we want to spread out the spikes to an approximately constant rate”

sleep = random_between(0, min(cap, base * 2 ** attempt))
retry(limitAttempts(5) + fullJitterBackoff(base = 10L, max = 5000L)) {
    /* code */
}

Equal Jitter

“Equal Jitter, where we always keep some of the backoff and jitter by a smaller amount”

temp = min(cap, base * 2 ** attempt)
sleep = temp / 2 + random_between(0, temp / 2)
retry(limitAttempts(5) + equalJitterBackoff(base = 10L, max = 5000L)) {
    /* code */
}

Decorrelated Jitter

“Decorrelated Jitter, which is similar to “Full Jitter”, but we also increase the maximum jitter based on the last random value”

sleep = min(cap, random_between(base, sleep * 3))
retry(limitAttempts(5) + decorrelatedJitterBackoff(base = 10L, max = 5000L)) {
    /* code */
}

Inspiration

Contributing

Bug reports and pull requests are welcome on GitHub.

License

This project is available under the terms of the ISC license. See the LICENSE file for the copyright information and licensing terms.




鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap