All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.valaphee.foundry.retry.policy.Backoff.kt Maven / Gradle / Ivy

/*
 * Copyright (c) 2021, Valaphee.
 * All rights reserved.
 */

@file:Suppress("NOTHING_TO_INLINE")

package com.valaphee.foundry.retry.policy

import com.valaphee.foundry.retry.ContinueRetrying
import com.valaphee.foundry.retry.context.retryRandom
import com.valaphee.foundry.retry.context.retryStatus
import com.valaphee.foundry.retry.exp2
import com.valaphee.foundry.retry.retryAfter
import com.valaphee.foundry.retry.sadd
import com.valaphee.foundry.retry.smul
import kotlin.coroutines.coroutineContext
import kotlin.math.max
import kotlin.math.min

fun binaryExponentialBackoff(base: Long, maximum: Long): RetryPolicy<*> {
    require(base > 0) { "base must be positive: $base" }
    require(maximum > 0) { "maximum must be positive: $maximum" }

    return { retryAfter(min(maximum, base smul coroutineContext.retryStatus.attempt.exp2())) }
}

inline fun binaryExponentialBackoff(range: LongRange) = binaryExponentialBackoff(range.first, range.last)

fun fullJitterBackoff(base: Long, maximum: Long): RetryPolicy<*> {
    require(base > 0) { "base must be positive: $base" }
    require(maximum > 0) { "maximum must be positive: $maximum" }

    return {
        val randomDelay = coroutineContext.retryRandom.random.nextLong(min(maximum, base smul coroutineContext.retryStatus.attempt.exp2()) sadd 1)
        if (randomDelay == 0L) ContinueRetrying else retryAfter(randomDelay)
    }
}

inline fun fullJitterBackoff(range: LongRange) = fullJitterBackoff(range.first, range.last)

fun equalJitterBackoff(base: Long, maximum: Long): RetryPolicy<*> {
    require(base > 0) { "base must be positive: $base" }
    require(maximum > 0) { "maximum must be positive: $maximum" }

    return {
        val delay = min(maximum, base smul coroutineContext.retryStatus.attempt.exp2())
        retryAfter((delay / 2) sadd coroutineContext.retryRandom.random.nextLong((delay / 2) sadd 1))
    }
}

inline fun equalJitterBackoff(range: LongRange) = equalJitterBackoff(range.first, range.last)

fun decorrelatedJitterBackoff(base: Long, maximum: Long): RetryPolicy<*> {
    require(base > 0) { "base must be positive: $base" }
    require(maximum > 0) { "maximum must be positive: $maximum" }

    return { retryAfter(min(maximum, coroutineContext.retryRandom.random.nextLong(base, max(base, coroutineContext.retryStatus.previousDelay smul 3) sadd 1))) }
}

inline fun decorrelatedJitterBackoff(range: LongRange) = decorrelatedJitterBackoff(range.first, range.last)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy