Use archive-specific endpoint for attachment backfill.

This commit is contained in:
Greyson Parrelli
2024-04-23 16:29:03 -04:00
committed by GitHub
parent f78a019c70
commit 4134df3f35
10 changed files with 170 additions and 95 deletions

View File

@@ -49,6 +49,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.Pro
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.push.ServiceId.PNI
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.InputStream
@@ -339,6 +340,24 @@ object BackupRepository {
}
}
/**
* Retrieves an upload spec that can be used to upload attachment media.
*/
fun getMediaUploadSpec(): NetworkResult<ResumableUploadSpec> {
val api = ApplicationDependencies.getSignalServiceAccountManager().archiveApi
val backupKey = SignalStore.svr().getOrCreateMasterKey().deriveBackupKey()
return api
.triggerBackupIdReservation(backupKey)
.then { getAuthCredential() }
.then { credential ->
api.getMediaUploadForm(backupKey, credential)
}
.then { form ->
api.getResumableUploadSpec(form)
}
}
fun archiveMedia(attachment: DatabaseAttachment): NetworkResult<Unit> {
val api = ApplicationDependencies.getSignalServiceAccountManager().archiveApi
val backupKey = SignalStore.svr().getOrCreateMasterKey().deriveBackupKey()

View File

@@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.jobs.protos.ArchiveAttachmentBackfillJobData
import org.whispersystems.signalservice.api.NetworkResult
import org.whispersystems.signalservice.api.archive.ArchiveMediaResponse
import org.whispersystems.signalservice.api.archive.ArchiveMediaUploadFormStatusCodes
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
import java.io.IOException
import java.util.Optional
@@ -123,7 +124,12 @@ class ArchiveAttachmentBackfillJob private constructor(
if (transferState == AttachmentTable.ArchiveTransferState.BACKFILL_UPLOAD_IN_PROGRESS) {
if (uploadSpec == null || System.currentTimeMillis() > uploadSpec!!.timeout) {
Log.d(TAG, "Need an upload spec. Fetching...")
uploadSpec = ApplicationDependencies.getSignalServiceMessageSender().getResumableUploadSpec().toProto()
val (spec, result) = fetchResumableUploadSpec()
if (result != null) {
return result
}
uploadSpec = spec
} else {
Log.d(TAG, "Already have an upload spec. Continuing...")
}
@@ -212,6 +218,42 @@ class ArchiveAttachmentBackfillJob private constructor(
}
}
private fun fetchResumableUploadSpec(): Pair<ResumableUpload?, Result?> {
return when (val spec = BackupRepository.getMediaUploadSpec()) {
is NetworkResult.Success -> {
Log.d(TAG, "Got an upload spec!")
spec.result.toProto() to null
}
is NetworkResult.ApplicationError -> {
Log.w(TAG, "Failed to get an upload spec due to an application error. Retrying.", spec.throwable)
return null to Result.retry(defaultBackoff())
}
is NetworkResult.NetworkError -> {
Log.w(TAG, "Encountered a transient network error. Retrying.")
return null to Result.retry(defaultBackoff())
}
is NetworkResult.StatusCodeError -> {
Log.w(TAG, "Failed request with status code ${spec.code}")
when (ArchiveMediaUploadFormStatusCodes.from(spec.code)) {
ArchiveMediaUploadFormStatusCodes.BadArguments,
ArchiveMediaUploadFormStatusCodes.InvalidPresentationOrSignature,
ArchiveMediaUploadFormStatusCodes.InsufficientPermissions,
ArchiveMediaUploadFormStatusCodes.RateLimited -> {
return null to Result.retry(defaultBackoff())
}
ArchiveMediaUploadFormStatusCodes.Unknown -> {
return null to Result.retry(defaultBackoff())
}
}
}
}
}
class Factory : Job.Factory<ArchiveAttachmentBackfillJob> {
override fun create(parameters: Parameters, serializedData: ByteArray?): ArchiveAttachmentBackfillJob {
val data = serializedData?.let { ArchiveAttachmentBackfillJobData.ADAPTER.decode(it) }