Skip to content

Commit

Permalink
Fix : Use ThreadLocalRandom instead of Random to calculate delay time
Browse files Browse the repository at this point in the history
Implement exponential backoff algorithm to calculate transaction delays
  • Loading branch information
mgrati committed Jun 20, 2023
1 parent c2c3c91 commit 89d66a1
Showing 1 changed file with 14 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.jetbrains.exposed.sql.exposedLogger
import org.jetbrains.exposed.sql.statements.api.ExposedConnection
import org.jetbrains.exposed.sql.statements.api.ExposedSavepoint
import java.sql.SQLException
import kotlin.random.Random
import java.util.concurrent.ThreadLocalRandom

class ThreadLocalTransactionManager(
private val db: Database,
Expand Down Expand Up @@ -232,6 +232,11 @@ fun <T> inTopLevelTransaction(

val outerManager = outerTransaction?.db.transactionManager.takeIf { it.currentOrNull() != null }

var intermediateDelay = minRepetitionDelay
var retryInterval = if (repetitionAttempts > 0) {
maxOf((maxRepetitionDelay - minRepetitionDelay) / (repetitionAttempts + 1), 1)
} else 0

while (true) {
db?.let { db.transactionManager.let { m -> TransactionManager.resetCurrent(m) } }
val transaction = db.transactionManager.newTransaction(transactionIsolation, readOnly, outerTransaction)
Expand All @@ -248,13 +253,14 @@ fun <T> inTopLevelTransaction(
if (repetitions >= repetitionAttempts) {
throw e
}
// set delay value
val delay = if (minRepetitionDelay < maxRepetitionDelay) {
Random(System.currentTimeMillis()).nextLong(minRepetitionDelay, maxRepetitionDelay)
} else if (minRepetitionDelay == maxRepetitionDelay) {
minRepetitionDelay
} else {
0
// set delay value with an exponential backoff time period.
val delay = when {
minRepetitionDelay < maxRepetitionDelay -> {
intermediateDelay += retryInterval * repetitions
ThreadLocalRandom.current().nextLong(intermediateDelay , intermediateDelay + retryInterval)
}
minRepetitionDelay == maxRepetitionDelay -> minRepetitionDelay
else -> 0
}
exposedLogger.warn("Wait $delay milliseconds before retrying")
try {
Expand Down

0 comments on commit 89d66a1

Please sign in to comment.