mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-05-08 09:18:39 +01:00
Fix backup jitter and add unit tests.
This commit is contained in:
@@ -47,14 +47,7 @@ public class LocalBackupListener extends PersistentAlarmManagerListener {
|
|||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
int hour = SignalStore.settings().getBackupHour();
|
int hour = SignalStore.settings().getBackupHour();
|
||||||
int minute = SignalStore.settings().getBackupMinute();
|
int minute = SignalStore.settings().getBackupMinute();
|
||||||
LocalDateTime next = now.withHour(hour).withMinute(minute).withSecond(0);
|
LocalDateTime next = MessageBackupListener.getNextDailyBackupTimeFromNowWithJitter(now, hour, minute, BACKUP_JITTER_WINDOW_SECONDS);
|
||||||
|
|
||||||
if (now.isAfter(next)) {
|
|
||||||
next = next.plusDays(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int jitter = (new Random().nextInt(BACKUP_JITTER_WINDOW_SECONDS)) - (BACKUP_JITTER_WINDOW_SECONDS / 2);
|
|
||||||
next = next.plusSeconds(jitter);
|
|
||||||
|
|
||||||
long nextTime = JavaTimeExtensionsKt.toMillis(next);
|
long nextTime = JavaTimeExtensionsKt.toMillis(next);
|
||||||
|
|
||||||
|
|||||||
@@ -41,21 +41,28 @@ class MessageBackupListener : PersistentAlarmManagerListener() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getNextDailyBackupTimeFromNowWithJitter(now: LocalDateTime, hour: Int, minute: Int, maxJitterSeconds: Int): LocalDateTime {
|
||||||
|
var next = now.withHour(hour).withMinute(minute).withSecond(0)
|
||||||
|
|
||||||
|
if (!now.plusSeconds(maxJitterSeconds.toLong() / 2).isBefore(next)) {
|
||||||
|
next = next.plusDays(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val jitter = Random().nextInt(BACKUP_JITTER_WINDOW_SECONDS) - BACKUP_JITTER_WINDOW_SECONDS / 2
|
||||||
|
return next.plusSeconds(jitter.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
fun setNextBackupTimeToIntervalFromNow(): Long {
|
fun setNextBackupTimeToIntervalFromNow(): Long {
|
||||||
val now = LocalDateTime.now()
|
val now = LocalDateTime.now()
|
||||||
val hour = SignalStore.settings().backupHour
|
val hour = SignalStore.settings().backupHour
|
||||||
val minute = SignalStore.settings().backupMinute
|
val minute = SignalStore.settings().backupMinute
|
||||||
var next = now.withHour(hour).withMinute(minute).withSecond(0)
|
var next = getNextDailyBackupTimeFromNowWithJitter(now, hour, minute, BACKUP_JITTER_WINDOW_SECONDS)
|
||||||
val jitter = Random().nextInt(BACKUP_JITTER_WINDOW_SECONDS) - BACKUP_JITTER_WINDOW_SECONDS / 2
|
|
||||||
next.plusSeconds(jitter.toLong())
|
|
||||||
next = when (SignalStore.backup().backupFrequency) {
|
next = when (SignalStore.backup().backupFrequency) {
|
||||||
BackupFrequency.DAILY -> next.plusDays(1)
|
BackupFrequency.MANUAL -> next.plusDays(364)
|
||||||
BackupFrequency.MANUAL -> next.plusDays(365)
|
BackupFrequency.MONTHLY -> next.plusDays(29)
|
||||||
BackupFrequency.MONTHLY -> next.plusDays(30)
|
BackupFrequency.WEEKLY -> next.plusDays(6)
|
||||||
BackupFrequency.WEEKLY -> next.plusDays(7)
|
else -> next
|
||||||
}
|
|
||||||
if (now.isAfter(next)) {
|
|
||||||
next = next.plusDays(1)
|
|
||||||
}
|
}
|
||||||
val nextTime = next.toMillis()
|
val nextTime = next.toMillis()
|
||||||
SignalStore.backup().nextBackupTime = nextTime
|
SignalStore.backup().nextBackupTime = nextTime
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.service
|
||||||
|
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import org.thoughtcrime.securesms.BaseUnitTest
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class BackListenerTest : BaseUnitTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBackupJitterExactlyWithinJitterWindow() {
|
||||||
|
val jitterWindowSeconds = Math.toIntExact(TimeUnit.MINUTES.toSeconds(10))
|
||||||
|
val now = LocalDateTime.of(2024, 6, 7, 2, 55)
|
||||||
|
val next = MessageBackupListener.getNextDailyBackupTimeFromNowWithJitter(now, 3, 0, jitterWindowSeconds)
|
||||||
|
Assert.assertEquals(8, next.dayOfMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBackupJitterWithinJitterWindow() {
|
||||||
|
val jitterWindowSeconds = Math.toIntExact(TimeUnit.MINUTES.toSeconds(10))
|
||||||
|
val now = LocalDateTime.of(2024, 6, 7, 2, 58)
|
||||||
|
val next = MessageBackupListener.getNextDailyBackupTimeFromNowWithJitter(now, 3, 0, jitterWindowSeconds)
|
||||||
|
Assert.assertEquals(8, next.dayOfMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBackupJitterJustOutsideOfWindow() {
|
||||||
|
val jitterWindowSeconds = Math.toIntExact(TimeUnit.MINUTES.toSeconds(10))
|
||||||
|
val now = LocalDateTime.of(2024, 6, 7, 2, 54, 59)
|
||||||
|
val next = MessageBackupListener.getNextDailyBackupTimeFromNowWithJitter(now, 3, 0, jitterWindowSeconds)
|
||||||
|
Assert.assertEquals(7, next.dayOfMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBackupJitter() {
|
||||||
|
val jitterWindowSeconds = Math.toIntExact(TimeUnit.MINUTES.toSeconds(10))
|
||||||
|
val now = LocalDateTime.of(2024, 6, 7, 3, 15, 0)
|
||||||
|
val next = MessageBackupListener.getNextDailyBackupTimeFromNowWithJitter(now, 3, 0, jitterWindowSeconds)
|
||||||
|
Assert.assertEquals(8, next.dayOfMonth)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user