Skip to content

Commit 83fa82b

Browse files
committed
create test to prove we don't wait after create
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.
1 parent bc61498 commit 83fa82b

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/ConfigModel.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,19 @@ class ConfigModel : Model() {
141141
setLongProperty(::opRepoPostWakeDelay.name, value)
142142
}
143143

144+
/**
145+
* The number milliseconds to delay after an operation completes
146+
* that creates or changes ids.
147+
* This is a "cold down" period to avoid a caveat with OneSignal's backend
148+
* replication, where you may incorrectly get a 404 when attempting a GET
149+
* or PATCH REST API call on something just after it is created.
150+
*/
151+
var opRepoPostCreateDelay: Long
152+
get() = getLongProperty(::opRepoPostCreateDelay.name) { 5_000 }
153+
set(value) {
154+
setLongProperty(::opRepoPostCreateDelay.name, value)
155+
}
156+
144157
/**
145158
* The minimum number of milliseconds required to pass to allow the fetching of IAM to occur.
146159
*/

OneSignalSDK/onesignal/core/src/test/java/com/onesignal/core/internal/operations/OperationRepoTests.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import io.mockk.slot
2323
import io.mockk.spyk
2424
import io.mockk.verify
2525
import kotlinx.coroutines.delay
26+
import kotlinx.coroutines.launch
2627
import kotlinx.coroutines.withTimeoutOrNull
28+
import kotlinx.coroutines.yield
2729

2830
// Mocks used by every test in this file
2931
private class Mocks {
@@ -485,6 +487,54 @@ class OperationRepoTests : FunSpec({
485487
executor.execute(withArg { it[0] shouldBe secondOp })
486488
}
487489
}
490+
491+
// This is to account for the case where we create a User or Subscription
492+
// and attempt to immediately access it (via GET or PATCH). A delay is
493+
// needed as the backend may incorrectly 404 otherwise, due to a small
494+
// delay in it's server replication.
495+
// A cold down period like this also helps improve batching as well.
496+
test("execution of an operation with translation IDs delays follow up operations") {
497+
// Given
498+
val mocks = Mocks()
499+
mocks.configModelStore.model.opRepoPostCreateDelay = 100
500+
val operation1 = mockOperation(groupComparisonType = GroupComparisonType.NONE)
501+
val operation2 = mockOperation(groupComparisonType = GroupComparisonType.NONE, applyToRecordId = "id2")
502+
val operation3 = mockOperation(groupComparisonType = GroupComparisonType.NONE)
503+
coEvery {
504+
mocks.executor.execute(listOf(operation1))
505+
} returns ExecutionResponse(ExecutionResult.SUCCESS, mapOf("local-id1" to "id2"))
506+
507+
// When
508+
mocks.operationRepo.start()
509+
mocks.operationRepo.enqueue(operation1)
510+
val job = launch { mocks.operationRepo.enqueueAndWait(operation2) }.also { yield() }
511+
mocks.operationRepo.enqueue(operation3)
512+
job.join()
513+
514+
// Then
515+
coVerifyOrder {
516+
mocks.executor.execute(
517+
withArg {
518+
it.count() shouldBe 1
519+
it[0] shouldBe operation1
520+
},
521+
)
522+
operation2.translateIds(mapOf("local-id1" to "id2"))
523+
mocks.executor.execute(
524+
withArg {
525+
it.count() shouldBe 1
526+
it[0] shouldBe operation3
527+
},
528+
)
529+
// Ensure operation2 runs after operation3 as it has to wait for the create delay
530+
mocks.executor.execute(
531+
withArg {
532+
it.count() shouldBe 1
533+
it[0] shouldBe operation2
534+
},
535+
)
536+
}
537+
}
488538
}) {
489539
companion object {
490540
private fun mockOperation(
@@ -495,6 +545,7 @@ class OperationRepoTests : FunSpec({
495545
createComparisonKey: String = "create-key",
496546
modifyComparisonKey: String = "modify-key",
497547
operationIdSlot: CapturingSlot<String>? = null,
548+
applyToRecordId: String = "",
498549
): Operation {
499550
val operation = mockk<Operation>()
500551
val opIdSlot = operationIdSlot ?: slot()

0 commit comments

Comments
 (0)