Skip to content

Commit

Permalink
RUM-2600: Add traversal flag to snapshot items
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanmos committed Jan 25, 2024
1 parent 8145782 commit b24509a
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ internal class RecordedDataQueueHandler {

internal companion object {
@VisibleForTesting
internal const val MAX_DELAY_MS = 200L
internal const val MAX_DELAY_MS = 1000L

private val THREAD_POOL_MAX_KEEP_ALIVE_MS = TimeUnit.SECONDS.toMillis(5)
private const val CORE_DEFAULT_POOL_SIZE = 1 // Only one thread will be kept alive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@ internal class SnapshotRecordedDataQueueItem(
recordedQueuedItemContext: RecordedQueuedItemContext,
internal val systemInformation: SystemInformation
) : RecordedDataQueueItem(recordedQueuedItemContext) {
internal var nodes = emptyList<Node>()
@Volatile internal var nodes = emptyList<Node>()

@Volatile internal var isFinishedTraversal = false
internal var pendingJobs = AtomicInteger(0)

override fun isValid(): Boolean {
if (!isFinishedTraversal) {
// item is always valid unless traversal has finished
return true
}

return nodes.isNotEmpty()
}

override fun isReady(): Boolean {
return pendingJobs.get() == 0
return isFinishedTraversal && pendingJobs.get() == 0
}

internal fun incrementPendingJobs() = pendingJobs.incrementAndGet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ internal class WindowsOnDrawListener(

if (nodes.isNotEmpty()) {
item.nodes = nodes
if (item.isReady()) {
recordedDataQueueHandler.tryToConsumeItems()
}
}

item.isFinishedTraversal = true

if (item.isReady()) {
recordedDataQueueHandler.tryToConsumeItems()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ internal class RecordedDataQueueHandlerTest {
// Given
val item = testedHandler.addSnapshotItem(mockSystemInformation) ?: fail("item is null")
item.nodes = fakeNodeData
item.isFinishedTraversal = true

whenever(mockTimeProvider.getDeviceTimestamp())
.thenReturn(item.recordedQueuedItemContext.timestamp)
Expand Down Expand Up @@ -464,6 +465,10 @@ internal class RecordedDataQueueHandlerTest {
val item2 = createFakeSnapshotItemWithDelayMs(2)
val item3 = createFakeSnapshotItemWithDelayMs(3)

item1.isFinishedTraversal = true
item2.isFinishedTraversal = true
item3.isFinishedTraversal = true

assertThat(testedHandler.recordedDataQueue.size).isEqualTo(3)
val itemTimestamp = item1.recordedQueuedItemContext.timestamp

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
package com.datadog.android.sessionreplay.internal.async

import com.datadog.android.sessionreplay.forge.ForgeConfigurator
import com.datadog.android.sessionreplay.internal.processor.RecordedQueuedItemContext
import com.datadog.android.sessionreplay.internal.recorder.SystemInformation
import fr.xgouchet.elmyr.annotation.Forgery
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
import fr.xgouchet.elmyr.junit5.ForgeExtension
Expand All @@ -15,6 +17,7 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.Extensions
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.junit.jupiter.MockitoSettings
import org.mockito.quality.Strictness
Expand All @@ -30,17 +33,24 @@ internal class SnapshotRecordedDataQueueItemTest {
@Forgery
lateinit var fakeSnapshotRecordedDataQueueItem: SnapshotRecordedDataQueueItem

lateinit var testedItem: SnapshotRecordedDataQueueItem
@Forgery
lateinit var fakeRecordedQueuedItemContext: RecordedQueuedItemContext

@Mock
lateinit var mockSystemInformation: SystemInformation

private lateinit var testedItem: SnapshotRecordedDataQueueItem

@BeforeEach
fun `set up`() {
testedItem = fakeSnapshotRecordedDataQueueItem
}

@Test
fun `M return false W isValid() { Snapshot with empty nodes }`() {
fun `M return false W isValid() { finished traversal with empty nodes }`() {
// Given
testedItem.nodes = emptyList()
testedItem.isFinishedTraversal = true

// Then
assertThat(testedItem.isValid()).isFalse()
Expand All @@ -52,15 +62,38 @@ internal class SnapshotRecordedDataQueueItemTest {
assertThat(testedItem.isValid()).isTrue()
}

@Test
fun `M return true W isValid() { fresh node that has not finished traversal }`() {
// Given
testedItem = SnapshotRecordedDataQueueItem(
fakeRecordedQueuedItemContext,
mockSystemInformation
)

// Then
assertThat(testedItem.isValid()).isTrue()
}

@Test
fun `M return true W isReady() { Snapshot with no pending images }`() {
// Given
testedItem.pendingJobs.set(0)
testedItem.isFinishedTraversal = true

// Then
assertThat(testedItem.isReady()).isTrue()
}

@Test
fun `M return false W isReady() { not finished traveral }`() {
// Given
testedItem.pendingJobs.set(0)
testedItem.isFinishedTraversal = false

// Then
assertThat(testedItem.isReady()).isFalse()
}

@Test
fun `M return false W isReady() { Snapshot with pending images greater than 0 }`() {
// Given
Expand Down

0 comments on commit b24509a

Please sign in to comment.