Only retrieve remote announcements during specific time window.

This commit is contained in:
Cody Henthorne
2026-04-28 17:19:44 -04:00
committed by Greyson Parrelli
parent a951c7edfe
commit fc9d3e11e8
2 changed files with 38 additions and 2 deletions
@@ -485,7 +485,7 @@ class JobDatabase(
/** Should only be used for debugging! */
fun debugResetBackoffInterval() {
writableDatabase.update(Jobs.TABLE_NAME, contentValuesOf(Jobs.NEXT_BACKOFF_INTERVAL to 0), null, null)
writableDatabase.update(Jobs.TABLE_NAME, contentValuesOf(Jobs.NEXT_BACKOFF_INTERVAL to 0, Jobs.INITIAL_DELAY to 0), null, null)
}
private fun JobSpec.toContentValues(): ContentValues {
@@ -35,8 +35,12 @@ import org.whispersystems.signalservice.internal.ServiceResponse
import java.io.IOException
import java.lang.Integer.max
import java.security.MessageDigest
import java.time.LocalTime
import java.time.ZonedDateTime
import java.util.Locale
import java.util.concurrent.TimeUnit
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
/**
* Retrieves and processes release channel messages.
@@ -52,6 +56,9 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
private val TAG = Log.tag(RetrieveRemoteAnnouncementsJob::class.java)
private val RETRIEVE_FREQUENCY = TimeUnit.DAYS.toMillis(3)
private val WINDOW_START = LocalTime.of(9, 0)
private val WINDOW_END = LocalTime.of(21, 0)
@JvmStatic
@JvmOverloads
fun enqueue(force: Boolean = false) {
@@ -65,13 +72,18 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
return
}
val windowDelay = calculateTimeToNextWindow()
if (windowDelay > Duration.ZERO) {
Log.i(TAG, "Outside window, delaying ${windowDelay.inWholeMinutes} minutes")
}
val job = RetrieveRemoteAnnouncementsJob(
force,
Parameters.Builder()
.setQueue("RetrieveReleaseChannelJob")
.setMaxInstancesForFactory(1)
.setMaxAttempts(3)
.addConstraint(NetworkConstraint.KEY)
.setInitialDelay(windowDelay.inWholeMilliseconds)
.build()
)
@@ -80,6 +92,23 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
.then(job)
.enqueue()
}
private fun calculateTimeToNextWindow(): Duration {
val now = ZonedDateTime.now()
val time = now.toLocalTime()
if (time.isAfter(WINDOW_START) && time.isBefore(WINDOW_END)) {
return Duration.ZERO
}
val next9am = if (time.isBefore(WINDOW_START)) {
now.with(WINDOW_START)
} else {
now.plusDays(1).with(WINDOW_START)
}
return (next9am.toInstant().toEpochMilli() - System.currentTimeMillis()).milliseconds
}
}
override fun serialize(): ByteArray? = JsonJobData.Builder().putBoolean(KEY_FORCE, force).serialize()
@@ -106,6 +135,13 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
return
}
val delay = calculateTimeToNextWindow()
if (delay > Duration.ZERO) {
Log.i(TAG, "Outside window, re-enqueuing")
enqueue(force = force)
return
}
val manifestMd5: ByteArray? = S3.getObjectMD5(MANIFEST)
if (manifestMd5 == null) {