Use config to determine deletion lifespan in storage service.

This commit is contained in:
Michelle Tang
2025-06-05 11:12:23 -04:00
committed by Greyson Parrelli
parent df2e88eaac
commit 6b6980811b
6 changed files with 53 additions and 14 deletions

View File

@@ -30,10 +30,10 @@ import org.thoughtcrime.securesms.database.ThreadTable.Companion.ID
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.storage.StorageSyncModels
import org.thoughtcrime.securesms.util.RemoteConfig
import org.whispersystems.signalservice.api.storage.SignalChatFolderRecord
import org.whispersystems.signalservice.api.storage.StorageId
import org.whispersystems.signalservice.api.util.UuidUtil
import java.util.concurrent.TimeUnit
import org.whispersystems.signalservice.internal.storage.protos.ChatFolderRecord as RemoteChatFolderRecord
/**
@@ -43,7 +43,6 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
companion object {
private val TAG = Log.tag(ChatFolderTable::class.java)
private val DELETED_LIFESPAN: Long = TimeUnit.DAYS.toMillis(30)
@JvmField
val CREATE_TABLE: Array<String> = arrayOf(ChatFolderTable.CREATE_TABLE, ChatFolderMembershipTable.CREATE_TABLE)
@@ -543,13 +542,13 @@ class ChatFolderTables(context: Context?, databaseHelper: SignalDatabase?) : Dat
}
/**
* Removes storageIds from folders that have been deleted for [DELETED_LIFESPAN].
* Removes storageIds from folders that have been deleted for [RemoteConfig.messageQueueTime].
*/
fun removeStorageIdsFromOldDeletedFolders(now: Long): Int {
return writableDatabase
.update(ChatFolderTable.TABLE_NAME)
.values(ChatFolderTable.STORAGE_SERVICE_ID to null)
.where("${ChatFolderTable.STORAGE_SERVICE_ID} NOT NULL AND ${ChatFolderTable.DELETED_TIMESTAMP_MS} > 0 AND ${ChatFolderTable.DELETED_TIMESTAMP_MS} < ?", now - DELETED_LIFESPAN)
.where("${ChatFolderTable.STORAGE_SERVICE_ID} NOT NULL AND ${ChatFolderTable.DELETED_TIMESTAMP_MS} > 0 AND ${ChatFolderTable.DELETED_TIMESTAMP_MS} < ?", now - RemoteConfig.messageQueueTime)
.run()
}

View File

@@ -34,11 +34,11 @@ import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.storage.StorageSyncModels
import org.thoughtcrime.securesms.storage.StorageSyncModels.toLocal
import org.thoughtcrime.securesms.util.RemoteConfig
import org.whispersystems.signalservice.api.storage.SignalNotificationProfileRecord
import org.whispersystems.signalservice.api.storage.StorageId
import org.whispersystems.signalservice.api.util.UuidUtil
import java.time.DayOfWeek
import kotlin.time.Duration.Companion.days
/**
* Database for maintaining Notification Profiles, Notification Profile Schedules, and Notification Profile allowed memebers.
@@ -47,7 +47,6 @@ class NotificationProfileTables(context: Context, databaseHelper: SignalDatabase
companion object {
private val TAG = Log.tag(NotificationProfileTable::class)
private val DELETED_LIFESPAN: Long = 30.days.inWholeMilliseconds
@JvmField
val CREATE_TABLE: Array<String> = arrayOf(NotificationProfileTable.CREATE_TABLE, NotificationProfileScheduleTable.CREATE_TABLE, NotificationProfileAllowedMembersTable.CREATE_TABLE)
@@ -496,13 +495,13 @@ class NotificationProfileTables(context: Context, databaseHelper: SignalDatabase
}
/**
* Removes storageIds from notification profiles that have been deleted for [DELETED_LIFESPAN].
* Removes storageIds from notification profiles that have been deleted for [RemoteConfig.messageQueueTime].
*/
fun removeStorageIdsFromOldDeletedProfiles(now: Long): Int {
return writableDatabase
.update(NotificationProfileTable.TABLE_NAME)
.values(NotificationProfileTable.STORAGE_SERVICE_ID to null)
.where("${NotificationProfileTable.STORAGE_SERVICE_ID} NOT NULL AND ${NotificationProfileTable.DELETED_TIMESTAMP_MS} > 0 AND ${NotificationProfileTable.DELETED_TIMESTAMP_MS} < ?", now - DELETED_LIFESPAN)
.where("${NotificationProfileTable.STORAGE_SERVICE_ID} NOT NULL AND ${NotificationProfileTable.DELETED_TIMESTAMP_MS} > 0 AND ${NotificationProfileTable.DELETED_TIMESTAMP_MS} < ?", now - RemoteConfig.messageQueueTime)
.run()
}

View File

@@ -120,7 +120,6 @@ import java.io.IOException
import java.util.Collections
import java.util.LinkedList
import java.util.Optional
import java.util.concurrent.TimeUnit
import kotlin.jvm.optionals.getOrNull
import kotlin.math.max
@@ -129,8 +128,6 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
val TAG = Log.tag(RecipientTable::class.java)
companion object {
private val UNREGISTERED_LIFESPAN: Long = TimeUnit.DAYS.toMillis(30)
const val TABLE_NAME = "recipient"
const val ID = "_id"
@@ -1091,14 +1088,14 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
/**
* Removes storageIds from unregistered recipients who were unregistered more than [UNREGISTERED_LIFESPAN] ago.
* Removes storageIds from unregistered recipients who were unregistered more than [RemoteConfig.messageQueueTime] ago.
* @return The number of rows affected.
*/
fun removeStorageIdsFromOldUnregisteredRecipients(now: Long): Int {
return writableDatabase
.update(TABLE_NAME)
.values(STORAGE_SERVICE_ID to null)
.where("$STORAGE_SERVICE_ID NOT NULL AND $UNREGISTERED_TIMESTAMP > 0 AND $UNREGISTERED_TIMESTAMP < ?", now - UNREGISTERED_LIFESPAN)
.where("$STORAGE_SERVICE_ID NOT NULL AND $UNREGISTERED_TIMESTAMP > 0 AND $UNREGISTERED_TIMESTAMP < ?", now - RemoteConfig.messageQueueTime)
.run()
}

View File

@@ -32,6 +32,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncModels
import org.thoughtcrime.securesms.storage.StorageSyncValidations
import org.thoughtcrime.securesms.storage.StoryDistributionListRecordProcessor
import org.thoughtcrime.securesms.transport.RetryLaterException
import org.thoughtcrime.securesms.util.RemoteConfig
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
@@ -63,6 +64,7 @@ import org.whispersystems.signalservice.internal.storage.protos.ManifestRecord
import java.io.IOException
import java.util.concurrent.TimeUnit
import java.util.stream.Collectors
import kotlin.time.Duration.Companion.milliseconds
/**
* Does a full sync of our local storage state with the remote storage state. Will write any pending
@@ -360,7 +362,7 @@ class StorageSyncJob private constructor(parameters: Parameters, private var loc
val removedDeletedFolders = SignalDatabase.chatFolders.removeStorageIdsFromOldDeletedFolders(System.currentTimeMillis())
val removedDeletedProfiles = SignalDatabase.notificationProfiles.removeStorageIdsFromOldDeletedProfiles(System.currentTimeMillis())
if (removedUnregistered > 0 || removedDeletedFolders > 0 || removedDeletedProfiles > 0) {
Log.i(TAG, "Removed $removedUnregistered unregistered, $removedDeletedFolders folders, $removedDeletedProfiles notification profiles from storage service that have been deleted for longer than 30 days.")
Log.i(TAG, "Removed $removedUnregistered unregistered, $removedDeletedFolders folders, $removedDeletedProfiles notification profiles from storage service that have been deleted for longer than ${RemoteConfig.messageQueueTime.milliseconds.inWholeDays} days.")
}
val localStorageIds = getAllLocalStorageIds(self)

View File

@@ -1114,5 +1114,16 @@ object RemoteConfig {
hotSwappable = true
)
/**
* Also determines how long an unregistered/deleted record should remain in storage service
*/
val messageQueueTime: Long by remoteValue(
key = "global.messageQueueTimeInSeconds",
hotSwappable = true
) { value ->
val inSeconds = value.asLong(45.days.inWholeSeconds)
inSeconds.seconds.inWholeMilliseconds
}
// endregion
}