-
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 #95 from Parsely/engagement_manager_coroutines
Engagement manager to coroutines
- Loading branch information
Showing
8 changed files
with
328 additions
and
195 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
120 changes: 0 additions & 120 deletions
120
parsely/src/main/java/com/parsely/parselyandroid/EngagementManager.java
This file was deleted.
Oops, something went wrong.
84 changes: 84 additions & 0 deletions
84
parsely/src/main/java/com/parsely/parselyandroid/EngagementManager.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,84 @@ | ||
package com.parsely.parselyandroid | ||
|
||
import kotlin.time.Duration | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Job | ||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.isActive | ||
import kotlinx.coroutines.launch | ||
|
||
/** | ||
* Engagement manager for article and video engagement. | ||
* | ||
* | ||
* Implemented to handle its own queuing of future executions to accomplish | ||
* two things: | ||
* | ||
* | ||
* 1. Flushing any engaged time before canceling. | ||
* 2. Progressive backoff for long engagements to save data. | ||
*/ | ||
internal class EngagementManager( | ||
private val parselyTracker: ParselyTracker, | ||
private var latestDelayMillis: Long, | ||
private val baseEvent: Map<String, Any>, | ||
private val intervalCalculator: HeartbeatIntervalCalculator, | ||
private val coroutineScope: CoroutineScope, | ||
private val clock: Clock, | ||
) { | ||
private var job: Job? = null | ||
private var totalTime: Long = 0 | ||
private var nextScheduledExecution: Long = 0 | ||
|
||
val isRunning: Boolean | ||
get() = job?.isActive ?: false | ||
|
||
fun start() { | ||
val startTime = clock.now | ||
job = coroutineScope.launch { | ||
while (isActive) { | ||
latestDelayMillis = intervalCalculator.calculate(startTime) | ||
nextScheduledExecution = clock.now.inWholeMilliseconds + latestDelayMillis | ||
delay(latestDelayMillis) | ||
doEnqueue(clock.now.inWholeMilliseconds) | ||
} | ||
} | ||
} | ||
|
||
fun stop() { | ||
job?.let { | ||
it.cancel() | ||
doEnqueue(nextScheduledExecution) | ||
} | ||
} | ||
|
||
fun isSameVideo(url: String, urlRef: String, metadata: ParselyVideoMetadata): Boolean { | ||
val baseMetadata = baseEvent["metadata"] as Map<String, Any>? | ||
return baseEvent["url"] == url && baseEvent["urlref"] == urlRef && baseMetadata!!["link"] == metadata.link && baseMetadata["duration"] as Int == metadata.durationSeconds | ||
} | ||
|
||
private fun doEnqueue(scheduledExecutionTime: Long) { | ||
// Create a copy of the base event to enqueue | ||
val event: MutableMap<String, Any> = HashMap( | ||
baseEvent | ||
) | ||
ParselyTracker.PLog(String.format("Enqueuing %s event.", event["action"])) | ||
|
||
// Update `ts` for the event since it's happening right now. | ||
val baseEventData = (event["data"] as Map<String, Any>?)!! | ||
val data: MutableMap<String, Any> = HashMap(baseEventData) | ||
data["ts"] = clock.now.inWholeMilliseconds | ||
event["data"] = data | ||
|
||
// Adjust inc by execution time in case we're late or early. | ||
val executionDiff = clock.now.inWholeMilliseconds - scheduledExecutionTime | ||
val inc = latestDelayMillis + executionDiff | ||
totalTime += inc | ||
event["inc"] = inc / 1000 | ||
event["tt"] = totalTime | ||
parselyTracker.enqueueEvent(event) | ||
} | ||
|
||
val intervalMillis: Double | ||
get() = latestDelayMillis.toDouble() | ||
} |
9 changes: 3 additions & 6 deletions
9
parsely/src/main/java/com/parsely/parselyandroid/HeartbeatIntervalCalculator.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
Oops, something went wrong.