Skip to content

Commit

Permalink
Merge pull request #2017 from OneSignal/feat/add_backoff_to_operation…
Browse files Browse the repository at this point in the history
…_retries

[Feat] Add backoff to OperationRepo when retrying network calls
  • Loading branch information
jkasten2 committed Mar 7, 2024
2 parents a557800 + 591098c commit c371096
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal class OperationRepo(
private class OperationQueueItem(
val operation: Operation,
val waiter: WaiterWithValue<Boolean>? = null,
var retries: Int = 0,
)

private val executorsMap: Map<String, IOperationExecutor>
Expand Down Expand Up @@ -200,10 +201,18 @@ internal class OperationRepo(
}
}
ExecutionResult.FAIL_RETRY -> {
Logging.error("Operation execution failed, retrying: $operations")
// add back all operations to the front of the queue to be re-executed.
var highestRetries = 0
synchronized(queue) {
ops.reversed().forEach { queue.add(0, it) }
ops.reversed().forEach {
if (++it.retries > highestRetries) {
highestRetries = it.retries
}
queue.add(0, it)
}
}
delayBeforeRetry(highestRetries)
}
ExecutionResult.FAIL_PAUSE_OPREPO -> {
Logging.error("Operation execution failed with eventual retry, pausing the operation repo: $operations")
Expand Down Expand Up @@ -237,6 +246,13 @@ internal class OperationRepo(
}
}

suspend fun delayBeforeRetry(retries: Int) {
val delayFor = retries * 15_000L
if (delayFor < 1) return
Logging.error("Operations being delay for: $delayFor")
delay(delayFor)
}

/**
* Given a starting operation, find and remove from the queue all other operations that
* can be executed along with the starting operation. The full list of operations, with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.slot
import io.mockk.spyk

class OperationRepoTests : FunSpec({

Expand Down Expand Up @@ -73,7 +74,15 @@ class OperationRepoTests : FunSpec({
every { mockOperationModelStore.remove(any()) } just runs

val operationRepo =
OperationRepo(listOf(mockExecutor), mockOperationModelStore, MockHelper.configModelStore(), MockHelper.time(1000))
spyk(
OperationRepo(
listOf(mockExecutor),
mockOperationModelStore,
MockHelper.configModelStore(),
MockHelper.time(1000),
),
)
coEvery { operationRepo.delayBeforeRetry(any()) } just runs

val operationIdSlot = slot<String>()
val operation = mockOperation(operationIdSlot = operationIdSlot)
Expand All @@ -93,6 +102,7 @@ class OperationRepoTests : FunSpec({
it[0] shouldBe operation
},
)
operationRepo.delayBeforeRetry(1)
mockExecutor.execute(
withArg {
it.count() shouldBe 1
Expand Down

0 comments on commit c371096

Please sign in to comment.