Skip to content

Commit

Permalink
Merge 88b036f into 8d29d97
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanosiano committed Sep 20, 2023
2 parents 8d29d97 + 88b036f commit 6d1a864
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ public final class ScreenshotEventProcessor implements EventProcessor, Integrati

private final @NotNull Debouncer debouncer;
private static final long DEBOUNCE_WAIT_TIME_MS = 2000;
private static final int DEBOUNCE_MAX_EXECUTIONS = 3;

public ScreenshotEventProcessor(
final @NotNull SentryAndroidOptions options,
final @NotNull BuildInfoProvider buildInfoProvider) {
this.options = Objects.requireNonNull(options, "SentryAndroidOptions is required");
this.buildInfoProvider =
Objects.requireNonNull(buildInfoProvider, "BuildInfoProvider is required");
this.debouncer = new Debouncer(AndroidCurrentDateProvider.getInstance(), DEBOUNCE_WAIT_TIME_MS);
this.debouncer = new Debouncer(AndroidCurrentDateProvider.getInstance(), DEBOUNCE_WAIT_TIME_MS, DEBOUNCE_MAX_EXECUTIONS);

if (options.isAttachScreenshot()) {
addIntegrationToSdkVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ public final class ViewHierarchyEventProcessor implements EventProcessor, Integr

private static final long CAPTURE_TIMEOUT_MS = 1000;
private static final long DEBOUNCE_WAIT_TIME_MS = 2000;
private static final int DEBOUNCE_MAX_EXECUTIONS = 3;

public ViewHierarchyEventProcessor(final @NotNull SentryAndroidOptions options) {
this.options = Objects.requireNonNull(options, "SentryAndroidOptions is required");
this.debouncer = new Debouncer(AndroidCurrentDateProvider.getInstance(), DEBOUNCE_WAIT_TIME_MS);
this.debouncer = new Debouncer(AndroidCurrentDateProvider.getInstance(), DEBOUNCE_WAIT_TIME_MS, DEBOUNCE_MAX_EXECUTIONS);

if (options.isAttachViewHierarchy()) {
addIntegrationToSdkVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ public class Debouncer {

private final long waitTimeMs;
private final @NotNull ICurrentDateProvider timeProvider;
private int executions = 0;
private final int maxExecutions;

private Long lastExecutionTime = null;

public Debouncer(final @NotNull ICurrentDateProvider timeProvider, final long waitTimeMs) {
public Debouncer(final @NotNull ICurrentDateProvider timeProvider, final long waitTimeMs, final int maxExecutions) {
this.timeProvider = timeProvider;
this.waitTimeMs = waitTimeMs;
this.maxExecutions = maxExecutions <= 0 ? 1 : maxExecutions;
}

/**
Expand All @@ -25,9 +28,15 @@ public Debouncer(final @NotNull ICurrentDateProvider timeProvider, final long wa
public boolean checkForDebounce() {
final long now = timeProvider.getCurrentTimeMillis();
if (lastExecutionTime == null || (lastExecutionTime + waitTimeMs) <= now) {
executions = 0;
lastExecutionTime = now;
return false;
}
executions++;
if (executions < maxExecutions) {
return false;
}
executions = 0;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class DebouncerTest {

override fun getCurrentTimeMillis(): Long = currentTimeMs

fun getDebouncer(waitTimeMs: Long = 3000): Debouncer {
return Debouncer(this, waitTimeMs)
fun getDebouncer(waitTimeMs: Long = 3000, maxExecutions: Int = 1): Debouncer {
return Debouncer(this, waitTimeMs, maxExecutions)
}
}

Expand Down Expand Up @@ -59,4 +59,48 @@ class DebouncerTest {
fixture.currentTimeMs = 4000
assertFalse(debouncer.checkForDebounce())
}

@Test
fun `Debouncer maxExecutions is always greater than 0`() {
fixture.currentTimeMs = 1000
val debouncer = fixture.getDebouncer(3000, -1)
assertFalse(debouncer.checkForDebounce())
assertTrue(debouncer.checkForDebounce())
}

@Test
fun `Debouncer should signal debounce after maxExecutions calls`() {
fixture.currentTimeMs = 1000
val debouncer = fixture.getDebouncer(3000, 3)
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
assertTrue(debouncer.checkForDebounce())
}

@Test
fun `Debouncer maxExecutions counter resets if the other invocation is late enough`() {
fixture.currentTimeMs = 1000
val debouncer = fixture.getDebouncer(3000, 3)
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())

// After waitTimeMs passes, the maxExecutions counter is reset
fixture.currentTimeMs = 4000
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
assertTrue(debouncer.checkForDebounce())
}

@Test
fun `Debouncer maxExecutions counter resets after maxExecutions`() {
fixture.currentTimeMs = 1000
val debouncer = fixture.getDebouncer(3000, 3)
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
assertTrue(debouncer.checkForDebounce())
assertFalse(debouncer.checkForDebounce())
}
}

0 comments on commit 6d1a864

Please sign in to comment.