Add backstop for ensuring attachment archive jobs are enqueued.

This commit is contained in:
Greyson Parrelli
2025-09-02 19:04:01 -04:00
parent 3b715bc461
commit 71dd1d9d8b
4 changed files with 35 additions and 0 deletions

View File

@@ -205,6 +205,7 @@ public class ApplicationContext extends Application implements AppForegroundObse
.addNonBlocking(AppDependencies::getBillingApi)
.addNonBlocking(this::ensureProfileUploaded)
.addNonBlocking(() -> AppDependencies.getExpireStoriesManager().scheduleIfNecessary())
.addNonBlocking(BackupRepository::maybeFixAnyDanglingAttachmentUploads)
.addPostRender(() -> AppDependencies.getDeletedCallEventManager().scheduleIfNecessary())
.addPostRender(() -> RateLimitUtil.retryAllRateLimitedMessages(this))
.addPostRender(this::initializeExpiringMessageManager)

View File

@@ -100,6 +100,7 @@ import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraint
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.jobmanager.impl.WifiConstraint
import org.thoughtcrime.securesms.jobs.ArchiveAttachmentBackfillJob
import org.thoughtcrime.securesms.jobs.AvatarGroupsV2DownloadJob
import org.thoughtcrime.securesms.jobs.BackupDeleteJob
import org.thoughtcrime.securesms.jobs.BackupMessagesJob
@@ -112,6 +113,7 @@ import org.thoughtcrime.securesms.jobs.RestoreAttachmentJob
import org.thoughtcrime.securesms.jobs.RestoreOptimizedMediaJob
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob
import org.thoughtcrime.securesms.jobs.UploadAttachmentToArchiveJob
import org.thoughtcrime.securesms.keyvalue.BackupValues.ArchiveServiceCredentials
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -613,6 +615,23 @@ object BackupRepository {
SignalStore.backup.snoozeDownloadNotifier()
}
@JvmStatic
fun maybeFixAnyDanglingAttachmentUploads() {
if (!SignalStore.backup.backsUpMedia || !AppDependencies.jobManager.areQueuesEmpty(UploadAttachmentToArchiveJob.QUEUES)) {
return
}
val pendingBytes = SignalDatabase.attachments.getPendingArchiveUploadBytes()
if (pendingBytes == 0L) {
return
}
Log.w(TAG, "There are ${pendingBytes.bytes.toUnitString(maxPlaces = 2)} of attachments that need to be uploaded to the archive, but no jobs for them! Attempting to fix.")
val resetCount = SignalDatabase.attachments.clearArchiveTransferStateForInProgressItems()
Log.w(TAG, "Cleared the archive transfer state of $resetCount attachments.")
AppDependencies.jobManager.add(ArchiveAttachmentBackfillJob())
}
/**
* Whether or not the "Your media will be deleted today" sheet should be displayed.
*/

View File

@@ -164,6 +164,10 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
}
}
}
viewModelScope.launch(Dispatchers.IO) {
BackupRepository.maybeFixAnyDanglingAttachmentUploads()
}
}
fun setCanBackUpUsingCellular(canBackUpUsingCellular: Boolean) {

View File

@@ -868,6 +868,17 @@ class AttachmentTable(
}
}
/**
* Resets the [ARCHIVE_TRANSFER_STATE] of any attachments that are currently in-progress of uploading.
*/
fun clearArchiveTransferStateForInProgressItems(): Int {
return writableDatabase
.update(TABLE_NAME)
.values(ARCHIVE_TRANSFER_STATE to ArchiveTransferState.NONE.value)
.where("$ARCHIVE_TRANSFER_STATE IN (${ArchiveTransferState.UPLOAD_IN_PROGRESS.value}, ${ArchiveTransferState.COPY_PENDING.value}, ${ArchiveTransferState.TEMPORARY_FAILURE.value})")
.run()
}
/**
* Marks eligible attachments as offloaded based on their received at timestamp, their last restore time,
* presence of thumbnail if media, and the full file being available in the archive.