-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #86 from Parsely/extract_flush_manager
- Loading branch information
Showing
6 changed files
with
200 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
parsely/src/main/java/com/parsely/parselyandroid/FlushManager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.parsely.parselyandroid | ||
|
||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Job | ||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.isActive | ||
import kotlinx.coroutines.launch | ||
|
||
/** | ||
* Manager for the event flush timer. | ||
* | ||
* | ||
* Handles stopping and starting the flush timer. The flush timer | ||
* controls how often we send events to Parse.ly servers. | ||
*/ | ||
internal class FlushManager( | ||
private val parselyTracker: ParselyTracker, | ||
val intervalMillis: Long, | ||
private val coroutineScope: CoroutineScope | ||
) { | ||
private var job: Job? = null | ||
|
||
fun start() { | ||
if (job?.isActive == true) return | ||
|
||
job = coroutineScope.launch { | ||
while (isActive) { | ||
delay(intervalMillis) | ||
parselyTracker.flushEvents() | ||
} | ||
} | ||
} | ||
|
||
fun stop() = job?.cancel() | ||
|
||
val isRunning: Boolean | ||
get() = job?.isActive ?: false | ||
} |
7 changes: 7 additions & 0 deletions
7
parsely/src/main/java/com/parsely/parselyandroid/ParselyCoroutineScope.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.parsely.parselyandroid | ||
|
||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.SupervisorJob | ||
|
||
val sdkScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
parsely/src/test/java/com/parsely/parselyandroid/FlushManagerTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package com.parsely.parselyandroid | ||
|
||
import androidx.test.core.app.ApplicationProvider | ||
import kotlin.time.Duration.Companion.seconds | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.test.advanceTimeBy | ||
import kotlinx.coroutines.test.runCurrent | ||
import kotlinx.coroutines.test.runTest | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import org.robolectric.RobolectricTestRunner | ||
|
||
@OptIn(ExperimentalCoroutinesApi::class) | ||
@RunWith(RobolectricTestRunner::class) | ||
class FlushManagerTest { | ||
|
||
private lateinit var sut: FlushManager | ||
private val tracker = FakeTracker() | ||
|
||
@Test | ||
fun `when timer starts and interval time passes, then flush queue`() = runTest { | ||
sut = FlushManager(tracker, DEFAULT_INTERVAL_MILLIS, backgroundScope) | ||
|
||
sut.start() | ||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS) | ||
runCurrent() | ||
|
||
assertThat(tracker.flushEventsCounter).isEqualTo(1) | ||
} | ||
|
||
@Test | ||
fun `when timer starts and three interval time passes, then flush queue 3 times`() = runTest { | ||
sut = FlushManager(tracker, DEFAULT_INTERVAL_MILLIS, backgroundScope) | ||
|
||
sut.start() | ||
advanceTimeBy(3 * DEFAULT_INTERVAL_MILLIS) | ||
runCurrent() | ||
|
||
assertThat(tracker.flushEventsCounter).isEqualTo(3) | ||
} | ||
|
||
@Test | ||
fun `when timer starts and is stopped after 2 intervals passes, then flush queue 2 times`() = | ||
runTest { | ||
sut = FlushManager(tracker, DEFAULT_INTERVAL_MILLIS, backgroundScope) | ||
|
||
sut.start() | ||
advanceTimeBy(2 * DEFAULT_INTERVAL_MILLIS) | ||
runCurrent() | ||
sut.stop() | ||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS) | ||
runCurrent() | ||
|
||
assertThat(tracker.flushEventsCounter).isEqualTo(2) | ||
} | ||
|
||
@Test | ||
fun `when timer starts, is stopped before end of interval and then time of interval passes, then do not flush queue`() = | ||
runTest { | ||
sut = FlushManager(tracker, DEFAULT_INTERVAL_MILLIS, backgroundScope) | ||
|
||
sut.start() | ||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS / 2) | ||
runCurrent() | ||
sut.stop() | ||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS / 2) | ||
runCurrent() | ||
|
||
assertThat(tracker.flushEventsCounter).isEqualTo(0) | ||
} | ||
|
||
@Test | ||
fun `when timer starts, and another timer starts after some time, then flush queue according to the first start`() = | ||
runTest { | ||
sut = FlushManager(tracker, DEFAULT_INTERVAL_MILLIS, backgroundScope) | ||
|
||
sut.start() | ||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS / 2) | ||
runCurrent() | ||
sut.start() | ||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS / 2) | ||
runCurrent() | ||
|
||
assertThat(tracker.flushEventsCounter).isEqualTo(1) | ||
|
||
advanceTimeBy(DEFAULT_INTERVAL_MILLIS / 2) | ||
runCurrent() | ||
|
||
assertThat(tracker.flushEventsCounter).isEqualTo(1) | ||
} | ||
|
||
private companion object { | ||
val DEFAULT_INTERVAL_MILLIS: Long = 30.seconds.inWholeMilliseconds | ||
} | ||
|
||
class FakeTracker : ParselyTracker( | ||
"", 0, ApplicationProvider.getApplicationContext() | ||
) { | ||
var flushEventsCounter = 0 | ||
|
||
override fun flushEvents() { | ||
flushEventsCounter++ | ||
} | ||
} | ||
} |