Convert Throttle to Kotlin

pull/1055/head
Alex Baker 4 years ago
parent 41f7d1da6b
commit 6e6fb3eada

@ -1,72 +0,0 @@
package org.tasks.notifications
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.tasks.Freeze
import org.tasks.time.DateTimeUtils
@RunWith(AndroidJUnit4::class)
class ThrottleTest {
private lateinit var sleeper: Throttle.Sleeper
private lateinit var throttle: Throttle
@Before
fun setUp() {
sleeper = Mockito.mock(Throttle.Sleeper::class.java)
throttle = Throttle(3, sleeper)
}
@After
fun tearDown() {
Mockito.verifyNoMoreInteractions(sleeper)
}
@Test
fun dontThrottle() {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now)
runAt(now)
runAt(now + 1000)
}
@Test
fun throttleForOneMillisecond() {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now)
runAt(now)
runAt(now + 999)
Mockito.verify(sleeper).sleep(1)
}
@Test
fun throttleForOneSecond() {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now)
runAt(now)
runAt(now)
Mockito.verify(sleeper).sleep(1000)
}
@Test
fun throttleMultiple() {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now + 200)
runAt(now + 600)
runAt(now + 700)
Mockito.verify(sleeper).sleep(300)
runAt(now + 750)
Mockito.verify(sleeper).sleep(450)
}
private fun runAt(millis: Long) {
Freeze.freezeAt(millis) { throttle.run {} }
}
}

@ -1,41 +0,0 @@
package org.tasks.notifications;
import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread;
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
class Throttle {
private final long[] throttle;
private final Sleeper sleeper;
private int oldest = 0;
Throttle(int ratePerSecond) {
this(ratePerSecond, Throttle::sleep);
}
Throttle(int ratePerSecond, Sleeper sleeper) {
this.sleeper = sleeper;
throttle = new long[ratePerSecond];
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {
}
}
synchronized void run(Runnable runnable) {
assertNotMainThread();
long sleep = throttle[oldest] - (currentTimeMillis() - 1000);
if (sleep > 0) {
sleeper.sleep(sleep);
}
runnable.run();
throttle[oldest] = currentTimeMillis();
oldest = (oldest + 1) % throttle.length;
}
public interface Sleeper {
void sleep(long millis);
}
}

@ -0,0 +1,22 @@
package org.tasks.notifications
import kotlinx.coroutines.delay
import org.tasks.time.DateTimeUtils
internal class Throttle constructor(
ratePerSecond: Int,
private val sleeper: suspend (Long) -> Unit = { delay(it) }) {
private val throttle: LongArray = LongArray(ratePerSecond)
private var oldest = 0
@Synchronized
suspend fun run(runnable: suspend () -> Unit) {
val sleep = throttle[oldest] - (DateTimeUtils.currentTimeMillis() - 1000)
if (sleep > 0) {
sleeper.invoke(sleep)
}
runnable.invoke()
throttle[oldest] = DateTimeUtils.currentTimeMillis()
oldest = (oldest + 1) % throttle.size
}
}

@ -0,0 +1,68 @@
package org.tasks.notifications
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.tasks.SuspendFreeze
import org.tasks.time.DateTimeUtils
@ExperimentalCoroutinesApi
class ThrottleTest {
private lateinit var sleep: ArrayList<Long>
private lateinit var throttle: Throttle
@Before
fun setUp() {
sleep = ArrayList()
throttle = Throttle(3) { sleep.add(it) }
}
@Test
fun dontThrottle() = runBlockingTest {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now)
runAt(now)
runAt(now + 1000)
assertTrue(sleep.isEmpty())
}
@Test
fun throttleForOneMillisecond() = runBlockingTest {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now)
runAt(now)
runAt(now + 999)
assertEquals(arrayListOf(1L), sleep)
}
@Test
fun throttleForOneSecond() = runBlockingTest {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now)
runAt(now)
runAt(now)
assertEquals(arrayListOf(1000L), sleep)
}
@Test
fun throttleMultiple() = runBlockingTest {
val now = DateTimeUtils.currentTimeMillis()
runAt(now)
runAt(now + 200)
runAt(now + 600)
runAt(now + 700)
assertEquals(arrayListOf(300L), sleep)
runAt(now + 750)
assertEquals(arrayListOf(300L, 450L), sleep)
}
private suspend fun runAt(millis: Long) {
SuspendFreeze.freezeAt(millis) { throttle.run {} }
}
}
Loading…
Cancel
Save