Skip to content

Commit 880533d

Browse files
committed
feat: add exponential backoff and retry logic for email vericiation
1 parent 6577055 commit 880533d

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

src/main/kotlin/com/dobby/backend/application/usecase/member/email/SendEmailCodeUseCase.kt

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import com.dobby.backend.domain.model.Verification
1111
import com.dobby.backend.infrastructure.database.entity.enums.VerificationStatus
1212
import com.dobby.backend.util.EmailUtils
1313
import kotlinx.coroutines.CoroutineScope
14+
import kotlinx.coroutines.delay
1415
import kotlinx.coroutines.launch
15-
import kotlinx.coroutines.withContext
16-
import org.springframework.stereotype.Component
16+
import org.slf4j.LoggerFactory
17+
import kotlin.math.pow
18+
import kotlin.random.Random
1719

1820
class SendEmailCodeUseCase(
1921
private val verificationGateway: VerificationGateway,
@@ -75,9 +77,34 @@ class SendEmailCodeUseCase(
7577
}
7678
}
7779

80+
private val logger = LoggerFactory.getLogger(SendEmailCodeUseCase::class.java)
81+
7882
private suspend fun sendVerificationEmail(univEmail: String, code: String) {
7983
val content = EMAIL_CONTENT_TEMPLATE.format(code)
80-
emailGateway.sendEmail(univEmail, EMAIL_SUBJECT, content)
84+
val maxRetries = 3
85+
86+
var attempt = 1
87+
while(attempt <= maxRetries) {
88+
try {
89+
emailGateway.sendEmail(univEmail, EMAIL_SUBJECT, content)
90+
return
91+
} catch (ex: Exception) {
92+
attempt += 1
93+
if(attempt >= maxRetries) {
94+
logger.error("Failed to send email verification to $univEmail after $maxRetries attempts.", ex)
95+
throw ex
96+
}
97+
val backOffTime = calculateBackOff(attempt)
98+
logger.warn("Retrying to sending email... Attempt: $attempt, Waiting: ${backOffTime}ms")
99+
delay(backOffTime)
100+
}
101+
}
102+
}
103+
104+
private fun calculateBackOff(attempt: Int): Long {
105+
val defaultDelay = 1000L
106+
val maxJitter = 500L
107+
return defaultDelay * (2.0.pow(attempt)).toLong() + Random.nextLong(0, maxJitter)
81108
}
82109

83110
companion object {

0 commit comments

Comments
 (0)