Add additional CDN reconciliations to BackupMediaSnapshotSyncJob.

Co-authored-by: Cody Henthorne <cody@signal.org>
This commit is contained in:
Greyson Parrelli
2025-04-25 11:03:26 -04:00
committed by Cody Henthorne
parent 85647f1258
commit f73d929feb
13 changed files with 434 additions and 45 deletions

View File

@@ -238,6 +238,23 @@ class AttachmentTableTest {
assertArrayEquals(digest, newDigest)
}
@Test
fun resetArchiveTransferStateByDigest_singleMatch() {
// Given an attachment with some digest
val blob = BlobProvider.getInstance().forData(byteArrayOf(1, 2, 3, 4, 5)).createForSingleSessionInMemory()
val attachment = createAttachment(1, blob, AttachmentTable.TransformProperties.empty())
val attachmentId = SignalDatabase.attachments.insertAttachmentsForMessage(-1L, listOf(attachment), emptyList()).values.first()
SignalDatabase.attachments.finalizeAttachmentAfterUpload(attachmentId, AttachmentTableTestUtil.createUploadResult(attachmentId))
SignalDatabase.attachments.setArchiveTransferState(attachmentId, AttachmentTable.ArchiveTransferState.FINISHED)
// Reset the transfer state by digest
val digest = SignalDatabase.attachments.getAttachment(attachmentId)!!.remoteDigest!!
SignalDatabase.attachments.resetArchiveTransferStateByDigest(digest)
// Verify it's been reset
assertThat(SignalDatabase.attachments.getAttachment(attachmentId)!!.archiveTransferState).isEqualTo(AttachmentTable.ArchiveTransferState.NONE)
}
private fun createAttachmentPointer(key: ByteArray, digest: ByteArray, size: Int): Attachment {
return PointerAttachment.forPointer(
pointer = Optional.of(

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.database
import org.signal.core.util.Base64
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.Cdn
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.signalservice.api.attachment.AttachmentUploadResult
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId
import kotlin.random.Random
object AttachmentTableTestUtil {
fun createUploadResult(attachmentId: AttachmentId, uploadTimestamp: Long = System.currentTimeMillis()): AttachmentUploadResult {
val databaseAttachment = SignalDatabase.attachments.getAttachment(attachmentId)!!
return AttachmentUploadResult(
remoteId = SignalServiceAttachmentRemoteId.V4("somewhere-${Random.nextLong()}"),
cdnNumber = Cdn.CDN_3.cdnNumber,
key = databaseAttachment.remoteKey?.let { Base64.decode(it) } ?: Util.getSecretBytes(64),
iv = databaseAttachment.remoteIv ?: Util.getSecretBytes(16),
digest = Random.nextBytes(32),
incrementalDigest = Random.nextBytes(16),
incrementalDigestChunkSize = 5,
uploadTimestamp = uploadTimestamp,
dataSize = databaseAttachment.size,
blurHash = databaseAttachment.blurHash?.hash
)
}
}

View File

@@ -28,8 +28,6 @@ import org.thoughtcrime.securesms.providers.BlobProvider
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.signalservice.api.attachment.AttachmentUploadResult
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream
import java.io.File
@@ -729,7 +727,7 @@ class AttachmentTableTest_deduping {
fun upload(attachmentId: AttachmentId, uploadTimestamp: Long = System.currentTimeMillis()) {
SignalDatabase.attachments.createKeyIvIfNecessary(attachmentId)
SignalDatabase.attachments.finalizeAttachmentAfterUpload(attachmentId, createUploadResult(attachmentId, uploadTimestamp))
SignalDatabase.attachments.finalizeAttachmentAfterUpload(attachmentId, AttachmentTableTestUtil.createUploadResult(attachmentId, uploadTimestamp))
val attachment = SignalDatabase.attachments.getAttachment(attachmentId)!!
SignalDatabase.attachments.setArchiveCdn(
@@ -875,23 +873,6 @@ class AttachmentTableTest_deduping {
private fun ByteArray.asMediaStream(): MediaStream {
return MediaStream(this.inputStream(), MediaUtil.IMAGE_JPEG, 2, 2)
}
private fun createUploadResult(attachmentId: AttachmentId, uploadTimestamp: Long = System.currentTimeMillis()): AttachmentUploadResult {
val databaseAttachment = SignalDatabase.attachments.getAttachment(attachmentId)!!
return AttachmentUploadResult(
remoteId = SignalServiceAttachmentRemoteId.V4("somewhere-${Random.nextLong()}"),
cdnNumber = Cdn.CDN_3.cdnNumber,
key = databaseAttachment.remoteKey?.let { Base64.decode(it) } ?: Util.getSecretBytes(64),
iv = databaseAttachment.remoteIv ?: Util.getSecretBytes(16),
digest = Random.nextBytes(32),
incrementalDigest = Random.nextBytes(16),
incrementalDigestChunkSize = 5,
uploadTimestamp = uploadTimestamp,
dataSize = databaseAttachment.size,
blurHash = databaseAttachment.blurHash?.hash
)
}
}
private fun test(content: TestContext.() -> Unit) {