Skip to content

Commit

Permalink
create test to prove we don't wait after create
Browse files Browse the repository at this point in the history
This is to account for the case where we create a User or Subscription
and attempt to immediately access it (via GET or PATCH). A delay is
needed as the backend may incorrectly 404 otherwise, due to a small
delay in it's server replication.
A cold down period like this also helps improve batching as well.
  • Loading branch information
jkasten2 committed Apr 17, 2024
1 parent bc61498 commit 83fa82b
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ class ConfigModel : Model() {
setLongProperty(::opRepoPostWakeDelay.name, value)
}

/**
* The number milliseconds to delay after an operation completes
* that creates or changes ids.
* This is a "cold down" period to avoid a caveat with OneSignal's backend
* replication, where you may incorrectly get a 404 when attempting a GET
* or PATCH REST API call on something just after it is created.
*/
var opRepoPostCreateDelay: Long
get() = getLongProperty(::opRepoPostCreateDelay.name) { 5_000 }
set(value) {
setLongProperty(::opRepoPostCreateDelay.name, value)
}

/**
* The minimum number of milliseconds required to pass to allow the fetching of IAM to occur.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import io.mockk.slot
import io.mockk.spyk
import io.mockk.verify
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.coroutines.yield

// Mocks used by every test in this file
private class Mocks {
Expand Down Expand Up @@ -485,6 +487,54 @@ class OperationRepoTests : FunSpec({
executor.execute(withArg { it[0] shouldBe secondOp })
}
}

// This is to account for the case where we create a User or Subscription
// and attempt to immediately access it (via GET or PATCH). A delay is
// needed as the backend may incorrectly 404 otherwise, due to a small
// delay in it's server replication.
// A cold down period like this also helps improve batching as well.
test("execution of an operation with translation IDs delays follow up operations") {
// Given
val mocks = Mocks()
mocks.configModelStore.model.opRepoPostCreateDelay = 100
val operation1 = mockOperation(groupComparisonType = GroupComparisonType.NONE)
val operation2 = mockOperation(groupComparisonType = GroupComparisonType.NONE, applyToRecordId = "id2")
val operation3 = mockOperation(groupComparisonType = GroupComparisonType.NONE)
coEvery {
mocks.executor.execute(listOf(operation1))
} returns ExecutionResponse(ExecutionResult.SUCCESS, mapOf("local-id1" to "id2"))

// When
mocks.operationRepo.start()
mocks.operationRepo.enqueue(operation1)
val job = launch { mocks.operationRepo.enqueueAndWait(operation2) }.also { yield() }
mocks.operationRepo.enqueue(operation3)
job.join()

// Then
coVerifyOrder {
mocks.executor.execute(
withArg {
it.count() shouldBe 1
it[0] shouldBe operation1
},
)
operation2.translateIds(mapOf("local-id1" to "id2"))
mocks.executor.execute(
withArg {
it.count() shouldBe 1
it[0] shouldBe operation3
},
)
// Ensure operation2 runs after operation3 as it has to wait for the create delay
mocks.executor.execute(
withArg {
it.count() shouldBe 1
it[0] shouldBe operation2
},
)
}
}
}) {
companion object {
private fun mockOperation(
Expand All @@ -495,6 +545,7 @@ class OperationRepoTests : FunSpec({
createComparisonKey: String = "create-key",
modifyComparisonKey: String = "modify-key",
operationIdSlot: CapturingSlot<String>? = null,
applyToRecordId: String = "",
): Operation {
val operation = mockk<Operation>()
val opIdSlot = operationIdSlot ?: slot()
Expand Down

0 comments on commit 83fa82b

Please sign in to comment.