mirror of
https://github.com/signalapp/Signal-iOS.git
synced 2025-12-05 01:10:41 +00:00
Drop TSAttachment fields from JobRecords
This commit is contained in:
@@ -75,6 +75,5 @@
|
||||
"TSRecipientReadReceipt": 12,
|
||||
"TSThread": 2,
|
||||
"TSUnreadIndicatorInteraction": 4,
|
||||
"TestModel": 59,
|
||||
"tsAttachmentMultisendJobRecord": 58
|
||||
}
|
||||
"TestModel": 59
|
||||
}
|
||||
|
||||
@@ -1207,7 +1207,6 @@
|
||||
724D47BC2B97C57C001BE973 /* GroupV2Snapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BB3C5A23C6644B001651FC /* GroupV2Snapshot.swift */; };
|
||||
724D47BD2B97C5B9001BE973 /* GroupsV2Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BB3C5823C6644B001651FC /* GroupsV2Utils.swift */; };
|
||||
724E68642C91FA73002199F3 /* DataHexadecimalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 724E68632C91FA73002199F3 /* DataHexadecimalTest.swift */; };
|
||||
725464EC2B9F6EB900EABFD2 /* Deprecated_TSAttachmentMultisendJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9C50FF22F495F60054A33F /* Deprecated_TSAttachmentMultisendJob.swift */; };
|
||||
725464F62B9FAC7600EABFD2 /* CGPointExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C612B3284E466B00B2199A /* CGPointExtensionsTest.swift */; };
|
||||
725465162BA00BE400EABFD2 /* NameResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50086B9B29DF5CB100F9C072 /* NameResolver.swift */; };
|
||||
725465172BA00CDB00EABFD2 /* NewAccountDiscovery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E446822AEDDEE007982E6 /* NewAccountDiscovery.swift */; };
|
||||
@@ -2515,7 +2514,6 @@
|
||||
D9AA37A02A86E0910088EFFB /* OutgoingCallEventSyncMessageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AA379F2A86E0910088EFFB /* OutgoingCallEventSyncMessageTest.swift */; };
|
||||
D9AA37A42A8A9A910088EFFB /* OutgoingGroupCallUpdateMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AA37A32A8A9A910088EFFB /* OutgoingGroupCallUpdateMessage.swift */; };
|
||||
D9AD1D9528B9955C00B42E6F /* TSInfoMessage+GroupUpdateType+NSAttributedStringTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AD1D9428B9955C00B42E6F /* TSInfoMessage+GroupUpdateType+NSAttributedStringTest.swift */; };
|
||||
D9AE0ACB29162C160063488B /* TSAttachmentMultisendJobRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AE0ACA29162C160063488B /* TSAttachmentMultisendJobRecord.swift */; };
|
||||
D9AE0ACF29186D7F0063488B /* IncomingContactSyncJobRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AE0ACE29186D7F0063488B /* IncomingContactSyncJobRecord.swift */; };
|
||||
D9AE0AD32918715E0063488B /* ReceiptCredentialRedemptionJobRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AE0AD22918715E0063488B /* ReceiptCredentialRedemptionJobRecord.swift */; };
|
||||
D9AE0AD5291877600063488B /* SendGiftBadgeJobRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AE0AD4291877600063488B /* SendGiftBadgeJobRecord.swift */; };
|
||||
@@ -4243,7 +4241,6 @@
|
||||
4C83AC4123C55D9C00D4F2E6 /* SignalBaseTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalBaseTest.swift; sourceTree = "<group>"; };
|
||||
4C8A6DFB22E5499300469AE7 /* MediaZoomAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaZoomAnimationController.swift; sourceTree = "<group>"; };
|
||||
4C8A6DFD22E54AFA00469AE7 /* MediaInteractiveDismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaInteractiveDismiss.swift; sourceTree = "<group>"; };
|
||||
4C9C50FF22F495F60054A33F /* Deprecated_TSAttachmentMultisendJob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Deprecated_TSAttachmentMultisendJob.swift; sourceTree = "<group>"; };
|
||||
4C9D347923679C13006A4307 /* ContactStreamTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactStreamTest.swift; sourceTree = "<group>"; };
|
||||
4C9D347E23689E06006A4307 /* IncomingContactSyncJobQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingContactSyncJobQueue.swift; sourceTree = "<group>"; };
|
||||
4CA46F4B219CCC630038ABDE /* MediaCaptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaCaptionView.swift; sourceTree = "<group>"; };
|
||||
@@ -6289,7 +6286,6 @@
|
||||
D9AA379F2A86E0910088EFFB /* OutgoingCallEventSyncMessageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingCallEventSyncMessageTest.swift; sourceTree = "<group>"; };
|
||||
D9AA37A32A8A9A910088EFFB /* OutgoingGroupCallUpdateMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingGroupCallUpdateMessage.swift; sourceTree = "<group>"; };
|
||||
D9AD1D9428B9955C00B42E6F /* TSInfoMessage+GroupUpdateType+NSAttributedStringTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSInfoMessage+GroupUpdateType+NSAttributedStringTest.swift"; sourceTree = "<group>"; };
|
||||
D9AE0ACA29162C160063488B /* TSAttachmentMultisendJobRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAttachmentMultisendJobRecord.swift; sourceTree = "<group>"; };
|
||||
D9AE0ACE29186D7F0063488B /* IncomingContactSyncJobRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingContactSyncJobRecord.swift; sourceTree = "<group>"; };
|
||||
D9AE0AD22918715E0063488B /* ReceiptCredentialRedemptionJobRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptCredentialRedemptionJobRecord.swift; sourceTree = "<group>"; };
|
||||
D9AE0AD4291877600063488B /* SendGiftBadgeJobRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendGiftBadgeJobRecord.swift; sourceTree = "<group>"; };
|
||||
@@ -12015,7 +12011,6 @@
|
||||
F9C5CA85289453B100548EEE /* JobRecords */,
|
||||
D9F9A63A2BFFFCC400EF13EC /* BulkDeleteInteractionJobQueue.swift */,
|
||||
D9DB37F82B72A770007B16C8 /* CallRecordDeleteAllJobQueue.swift */,
|
||||
4C9C50FF22F495F60054A33F /* Deprecated_TSAttachmentMultisendJob.swift */,
|
||||
886A58C9276A760600A1099B /* DonationReceiptCredentialRedemptionJobQueue.swift */,
|
||||
4C9D347E23689E06006A4307 /* IncomingContactSyncJobQueue.swift */,
|
||||
5008FEBB2B1811A0004E73FD /* JobQueueRunner.swift */,
|
||||
@@ -13670,7 +13665,6 @@
|
||||
D9AE0AD22918715E0063488B /* ReceiptCredentialRedemptionJobRecord.swift */,
|
||||
D9AE0AD4291877600063488B /* SendGiftBadgeJobRecord.swift */,
|
||||
D9AE0AD629187A700063488B /* SessionResetJobRecord.swift */,
|
||||
D9AE0ACA29162C160063488B /* TSAttachmentMultisendJobRecord.swift */,
|
||||
);
|
||||
path = JobRecords;
|
||||
sourceTree = "<group>";
|
||||
@@ -17044,7 +17038,6 @@
|
||||
D9247EA82BFD28E800DFEF6F /* DeleteForMeSyncMessageReceiver.swift in Sources */,
|
||||
F9C5CC34289453B300548EEE /* DeliveryReceiptContext.swift in Sources */,
|
||||
6698FC1A2980AB45004EFC30 /* DependenciesBridge.swift in Sources */,
|
||||
725464EC2B9F6EB900EABFD2 /* Deprecated_TSAttachmentMultisendJob.swift in Sources */,
|
||||
505C2ED629971D4E00C23FB2 /* DeviceLimitExceededError.swift in Sources */,
|
||||
50E5E4B129932D9B00E15A1C /* DeviceMessage.swift in Sources */,
|
||||
F9C5CE0C289453B400548EEE /* DeviceNames.swift in Sources */,
|
||||
@@ -17863,7 +17856,6 @@
|
||||
665C758C2C35A55300D2E4BA /* TSAttachmentMigration+ThreadWallpaper.swift in Sources */,
|
||||
6660C7972C45C34A00D9C30A /* TSAttachmentMigration+TSMessage.swift in Sources */,
|
||||
66A1ABE22C3311B40033C5EB /* TSAttachmentMigration.swift in Sources */,
|
||||
D9AE0ACB29162C160063488B /* TSAttachmentMultisendJobRecord.swift in Sources */,
|
||||
F9C5CC79289453B300548EEE /* TSAttachmentPointer+SDS.swift in Sources */,
|
||||
F9C5CC78289453B300548EEE /* TSAttachmentPointer.m in Sources */,
|
||||
F9C5CC7B289453B300548EEE /* TSAttachmentStream+SDS.swift in Sources */,
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
//
|
||||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
public struct TSAttachmentMultisendResult {
|
||||
/// Resolved when the attachments are uploaded and sending is enqueued.
|
||||
public let enqueuedPromise: Promise<Void>
|
||||
/// Resolved when the message is sent.
|
||||
public let sentPromise: Promise<Void>
|
||||
}
|
||||
|
||||
public class TSAttachmentMultisendJobQueue {
|
||||
private let jobQueueRunner: JobQueueRunner<
|
||||
JobRecordFinderImpl<TSAttachmentMultisendJobRecord>,
|
||||
TSAttachmentMultisendJobRunnerFactory
|
||||
>
|
||||
private let jobRunnerFactory: TSAttachmentMultisendJobRunnerFactory
|
||||
|
||||
public init(db: any DB, reachabilityManager: SSKReachabilityManager) {
|
||||
self.jobRunnerFactory = TSAttachmentMultisendJobRunnerFactory()
|
||||
self.jobQueueRunner = JobQueueRunner(
|
||||
canExecuteJobsConcurrently: false,
|
||||
db: db,
|
||||
jobFinder: JobRecordFinderImpl(db: db),
|
||||
jobRunnerFactory: jobRunnerFactory
|
||||
)
|
||||
self.jobQueueRunner.listenForReachabilityChanges(reachabilityManager: reachabilityManager)
|
||||
}
|
||||
|
||||
public func start(appContext: AppContext) {
|
||||
if appContext.isNSE { return }
|
||||
jobQueueRunner.start(shouldRestartExistingJobs: appContext.isMainApp)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func add(
|
||||
attachmentIdMap: [String: [String]],
|
||||
storyMessagesToSend: [OutgoingStoryMessage],
|
||||
transaction: SDSAnyWriteTransaction
|
||||
) -> TSAttachmentMultisendResult {
|
||||
let jobRecord = TSAttachmentMultisendJobRecord(
|
||||
attachmentIdMap: attachmentIdMap,
|
||||
storyMessagesToSend: storyMessagesToSend
|
||||
)
|
||||
jobRecord.anyInsert(transaction: transaction)
|
||||
|
||||
let enqueuePromise = Promise<Void>.pending()
|
||||
let sendPromise = Promise<Void>.pending()
|
||||
let jobFutures = TSAttachmentMultisendFutures(
|
||||
enqueuedFuture: enqueuePromise.1,
|
||||
sentFuture: sendPromise.1
|
||||
)
|
||||
|
||||
transaction.addSyncCompletion {
|
||||
let runner = self.jobRunnerFactory.buildRunner(jobFutures)
|
||||
self.jobQueueRunner.addPersistedJob(jobRecord, runner: runner)
|
||||
}
|
||||
|
||||
return .init(
|
||||
enqueuedPromise: enqueuePromise.0,
|
||||
sentPromise: sendPromise.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class TSAttachmentMultisendFutures {
|
||||
/// Resolved when the attachments are uploaded and sending is enqueued.
|
||||
public let enqueuedFuture: Future<Void>
|
||||
/// Resolved when the message is sent.
|
||||
public let sentFuture: Future<Void>
|
||||
|
||||
init(enqueuedFuture: Future<Void>, sentFuture: Future<Void>) {
|
||||
self.enqueuedFuture = enqueuedFuture
|
||||
self.sentFuture = sentFuture
|
||||
}
|
||||
}
|
||||
|
||||
private class TSAttachmentMultisendJobRunnerFactory: JobRunnerFactory {
|
||||
|
||||
func buildRunner() -> TSAttachmentMultisendJobRunner {
|
||||
TSAttachmentMultisendJobRunner(jobFutures: nil)
|
||||
}
|
||||
|
||||
func buildRunner(_ jobFutures: TSAttachmentMultisendFutures?) -> TSAttachmentMultisendJobRunner {
|
||||
TSAttachmentMultisendJobRunner(jobFutures: jobFutures)
|
||||
}
|
||||
}
|
||||
|
||||
private class TSAttachmentMultisendJobRunner: JobRunner {
|
||||
|
||||
private let jobFutures: TSAttachmentMultisendFutures?
|
||||
|
||||
init(jobFutures: TSAttachmentMultisendFutures?) {
|
||||
self.jobFutures = jobFutures
|
||||
}
|
||||
|
||||
func runJobAttempt(_ jobRecord: TSAttachmentMultisendJobRecord) async -> JobAttemptResult {
|
||||
owsFailDebug("TSAttachment is obsoleted")
|
||||
await SSKEnvironment.shared.databaseStorageRef.awaitableWrite { transaction in
|
||||
jobRecord.anyRemove(transaction: transaction)
|
||||
}
|
||||
return .finished(.success(()))
|
||||
}
|
||||
|
||||
func didFinishJob(_ jobRecordId: JobRecord.RowId, result: JobResult) async {
|
||||
switch result.ranSuccessfullyOrError {
|
||||
case .success:
|
||||
// When this job finishes, the send is enqueued.
|
||||
// Send future resolution is handled within the job.
|
||||
jobFutures?.enqueuedFuture.resolve(())
|
||||
case .failure(let error):
|
||||
jobFutures?.enqueuedFuture.reject(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,6 @@ private class IncomingContactSyncJobRunner: JobRunner {
|
||||
|
||||
private func _runJob(_ jobRecord: IncomingContactSyncJobRecord) async throws {
|
||||
let fileUrl: URL
|
||||
let legacyAttachmentId: String?
|
||||
switch jobRecord.downloadInfo {
|
||||
case .invalid:
|
||||
owsFailDebug("Invalid contact sync job!")
|
||||
@@ -99,17 +98,10 @@ private class IncomingContactSyncJobRunner: JobRunner {
|
||||
jobRecord.anyRemove(transaction: tx)
|
||||
}
|
||||
return
|
||||
case .legacy(let attachmentId):
|
||||
owsFailDebug("Legacy jobs no longer supported")
|
||||
await SSKEnvironment.shared.databaseStorageRef.awaitableWrite { tx in
|
||||
jobRecord.anyRemove(transaction: tx)
|
||||
}
|
||||
return
|
||||
case .transient(let downloadMetadata):
|
||||
fileUrl = try await DependenciesBridge.shared.attachmentDownloadManager.downloadTransientAttachment(
|
||||
metadata: downloadMetadata
|
||||
).awaitable()
|
||||
legacyAttachmentId = nil
|
||||
}
|
||||
|
||||
let insertedThreads = try await firstly(on: DispatchQueue.global()) {
|
||||
|
||||
@@ -9,8 +9,6 @@ import GRDB
|
||||
public final class IncomingContactSyncJobRecord: JobRecord, FactoryInitializableFromRecordType {
|
||||
override class var jobRecordType: JobRecordType { .incomingContactSync }
|
||||
|
||||
private let legacyAttachmentId: String?
|
||||
|
||||
private let cdnNumber: UInt32?
|
||||
private let cdnKey: String?
|
||||
private let encryptionKey: Data?
|
||||
@@ -19,7 +17,6 @@ public final class IncomingContactSyncJobRecord: JobRecord, FactoryInitializable
|
||||
|
||||
public enum DownloadInfo {
|
||||
case invalid
|
||||
case legacy(attachmentId: String)
|
||||
case transient(AttachmentDownloads.DownloadMetadata)
|
||||
}
|
||||
|
||||
@@ -50,64 +47,21 @@ public final class IncomingContactSyncJobRecord: JobRecord, FactoryInitializable
|
||||
&& plaintextLength == nil,
|
||||
"Either all fields should be set or none!"
|
||||
)
|
||||
if let legacyAttachmentId {
|
||||
return .legacy(attachmentId: legacyAttachmentId)
|
||||
}
|
||||
return .invalid
|
||||
}
|
||||
|
||||
public let isCompleteContactSync: Bool
|
||||
|
||||
public static func legacy(
|
||||
legacyAttachmentId: String?,
|
||||
isCompleteContactSync: Bool,
|
||||
failureCount: UInt = 0,
|
||||
status: Status = .ready
|
||||
) -> IncomingContactSyncJobRecord {
|
||||
return IncomingContactSyncJobRecord(
|
||||
legacyAttachmentId: legacyAttachmentId,
|
||||
cdnNumber: nil,
|
||||
cdnKey: nil,
|
||||
encryptionKey: nil,
|
||||
digest: nil,
|
||||
plaintextLength: nil,
|
||||
isCompleteContactSync: isCompleteContactSync,
|
||||
failureCount: failureCount,
|
||||
status: status
|
||||
)
|
||||
}
|
||||
|
||||
public convenience init(
|
||||
public init(
|
||||
cdnNumber: UInt32,
|
||||
cdnKey: String,
|
||||
encryptionKey: Data,
|
||||
digest: Data,
|
||||
plaintextLength: UInt32?,
|
||||
isCompleteContactSync: Bool
|
||||
) {
|
||||
self.init(
|
||||
legacyAttachmentId: nil,
|
||||
cdnNumber: cdnNumber,
|
||||
cdnKey: cdnKey,
|
||||
encryptionKey: encryptionKey,
|
||||
digest: digest,
|
||||
plaintextLength: plaintextLength,
|
||||
isCompleteContactSync: isCompleteContactSync
|
||||
)
|
||||
}
|
||||
|
||||
private init(
|
||||
legacyAttachmentId: String?,
|
||||
cdnNumber: UInt32?,
|
||||
cdnKey: String?,
|
||||
encryptionKey: Data?,
|
||||
digest: Data?,
|
||||
plaintextLength: UInt32?,
|
||||
isCompleteContactSync: Bool,
|
||||
failureCount: UInt = 0,
|
||||
status: Status = .ready
|
||||
) {
|
||||
self.legacyAttachmentId = legacyAttachmentId
|
||||
self.isCompleteContactSync = isCompleteContactSync
|
||||
|
||||
self.cdnNumber = cdnNumber
|
||||
@@ -122,11 +76,35 @@ public final class IncomingContactSyncJobRecord: JobRecord, FactoryInitializable
|
||||
)
|
||||
}
|
||||
|
||||
#if TESTABLE_BUILD
|
||||
public init(
|
||||
cdnNumber: UInt32?,
|
||||
cdnKey: String?,
|
||||
encryptionKey: Data?,
|
||||
digest: Data?,
|
||||
plaintextLength: UInt32?,
|
||||
isCompleteContactSync: Bool,
|
||||
failureCount: UInt = 0,
|
||||
status: Status = .ready
|
||||
) {
|
||||
self.isCompleteContactSync = isCompleteContactSync
|
||||
|
||||
self.cdnNumber = cdnNumber
|
||||
self.cdnKey = cdnKey
|
||||
self.encryptionKey = encryptionKey
|
||||
self.digest = digest
|
||||
self.plaintextLength = plaintextLength
|
||||
|
||||
super.init(
|
||||
failureCount: failureCount,
|
||||
status: status
|
||||
)
|
||||
}
|
||||
#endif
|
||||
|
||||
required init(forRecordTypeFactoryInitializationFrom decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
legacyAttachmentId = try container.decodeIfPresent(String.self, forKey: .legacyAttachmentId)
|
||||
|
||||
cdnNumber = try container.decodeIfPresent(UInt32.self, forKey: .ICSJR_cdnNumber)
|
||||
cdnKey = try container.decodeIfPresent(String.self, forKey: .ICSJR_cdnKey)
|
||||
encryptionKey = try container.decodeIfPresent(Data.self, forKey: .ICSJR_encryptionKey)
|
||||
@@ -143,8 +121,6 @@ public final class IncomingContactSyncJobRecord: JobRecord, FactoryInitializable
|
||||
|
||||
try super.encode(to: container.superEncoder())
|
||||
|
||||
try container.encodeIfPresent(legacyAttachmentId, forKey: .legacyAttachmentId)
|
||||
|
||||
try container.encodeIfPresent(cdnNumber, forKey: .ICSJR_cdnNumber)
|
||||
try container.encodeIfPresent(cdnKey, forKey: .ICSJR_cdnKey)
|
||||
try container.encodeIfPresent(encryptionKey, forKey: .ICSJR_encryptionKey)
|
||||
|
||||
@@ -49,20 +49,11 @@ extension JobRecord {
|
||||
case ICSJR_digest
|
||||
case ICSJR_plaintextLength
|
||||
|
||||
// MARK: IncomingContactSyncJobRecord & IncomingGroupSyncJobRecord
|
||||
|
||||
case legacyAttachmentId = "attachmentId"
|
||||
|
||||
// MARK: LocalUserLeaveGroupJobRecord
|
||||
|
||||
case replacementAdminAciString = "replacementAdminUuid"
|
||||
case waitForMessageProcessing
|
||||
|
||||
// MARK: TSAttachmentMultisendJobRecord
|
||||
|
||||
case attachmentIdMap
|
||||
case unsavedMessagesToSend
|
||||
|
||||
// MARK: SessionResetJobRecord
|
||||
|
||||
case contactThreadId
|
||||
|
||||
@@ -24,7 +24,6 @@ extension JobRecord: NeedsFactoryInitializationFromRecordType {
|
||||
|
||||
// MARK: Values originally from SDSRecordType
|
||||
|
||||
case tsAttachmentMultisend = 58
|
||||
case incomingContactSync = 61
|
||||
case legacyMessageDecrypt = 53
|
||||
case localUserLeaveGroup = 74
|
||||
@@ -49,7 +48,6 @@ extension JobRecord: NeedsFactoryInitializationFromRecordType {
|
||||
}
|
||||
|
||||
switch jobRecordType {
|
||||
case .tsAttachmentMultisend: return TSAttachmentMultisendJobRecord.self
|
||||
case .incomingContactSync: return IncomingContactSyncJobRecord.self
|
||||
case .legacyMessageDecrypt: return LegacyMessageDecryptJobRecord.self
|
||||
case .localUserLeaveGroup: return LocalUserLeaveGroupJobRecord.self
|
||||
@@ -67,9 +65,6 @@ extension JobRecord.JobRecordType {
|
||||
var jobRecordLabel: String {
|
||||
// These values are persisted and must not change, even if they're misspelled.
|
||||
switch self {
|
||||
case .tsAttachmentMultisend:
|
||||
// label is serialized and must remain unchanged.
|
||||
return "BroadcastMediaMessage"
|
||||
case .incomingContactSync:
|
||||
return "IncomingContactSync"
|
||||
case .legacyMessageDecrypt:
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
//
|
||||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
public final class TSAttachmentMultisendJobRecord: JobRecord, FactoryInitializableFromRecordType {
|
||||
override class var jobRecordType: JobRecordType { .tsAttachmentMultisend }
|
||||
|
||||
/// A map from the TSAttachmentStream's to upload to their corresponding list of visible copies in individual
|
||||
/// conversations. e.g. if we're broadcast-sending a picture and a video to 3 recipients, the dictionary would look
|
||||
/// like:
|
||||
/// [
|
||||
/// pictureAttachmentId: [
|
||||
/// pictureCopyAttachmentIdForRecipient1,
|
||||
/// pictureCopyAttachmentIdForRecipient2,
|
||||
/// pictureCopyAttachmentIdForRecipient3
|
||||
/// ],
|
||||
/// videoAttachmentId: [
|
||||
/// videoCopyAttachmentIdForRecipient1,
|
||||
/// videoCopyAttachmentIdForRecipient2,
|
||||
/// videoCopyAttachmentIdForRecipient3
|
||||
/// ]
|
||||
/// ]
|
||||
public let attachmentIdMap: [String: [String]]
|
||||
|
||||
// These have always been only OutgoingStoryMessages, but rather than touch the serialization
|
||||
// layer, we just transform them in memory.
|
||||
// This class's public API takes OutgoingStoryMessage(s) and returns OutgoingStoryMessage(s).
|
||||
private let unsavedMessagesToSend: [TSOutgoingMessage]?
|
||||
|
||||
public var storyMessagesToSend: [OutgoingStoryMessage]? {
|
||||
return unsavedMessagesToSend?.compactMap { $0 as? OutgoingStoryMessage }
|
||||
}
|
||||
|
||||
public init(
|
||||
attachmentIdMap: [String: [String]],
|
||||
storyMessagesToSend: [OutgoingStoryMessage]?,
|
||||
failureCount: UInt = 0,
|
||||
status: Status = .ready
|
||||
) {
|
||||
self.attachmentIdMap = attachmentIdMap
|
||||
self.unsavedMessagesToSend = storyMessagesToSend
|
||||
|
||||
super.init(
|
||||
failureCount: failureCount,
|
||||
status: status
|
||||
)
|
||||
}
|
||||
|
||||
required init(forRecordTypeFactoryInitializationFrom decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
attachmentIdMap = try LegacySDSSerializer().deserializeLegacySDSData(
|
||||
try container.decode(Data.self, forKey: .attachmentIdMap),
|
||||
propertyName: "attachmentIdMap"
|
||||
)
|
||||
|
||||
unsavedMessagesToSend = try container.decodeIfPresent(
|
||||
Data.self,
|
||||
forKey: .unsavedMessagesToSend
|
||||
).map { unsavedMessagesToSendData in
|
||||
try LegacySDSSerializer().deserializeLegacySDSData(
|
||||
unsavedMessagesToSendData,
|
||||
propertyName: "unsavedMessagesToSend"
|
||||
)
|
||||
}
|
||||
|
||||
try super.init(baseClassDuringFactoryInitializationFrom: try container.superDecoder())
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try super.encode(to: container.superEncoder())
|
||||
|
||||
try container.encode(
|
||||
LegacySDSSerializer().serializeAsLegacySDSData(property: attachmentIdMap),
|
||||
forKey: .attachmentIdMap
|
||||
)
|
||||
|
||||
try container.encodeIfPresent(
|
||||
LegacySDSSerializer().serializeAsLegacySDSData(property: unsavedMessagesToSend),
|
||||
forKey: .unsavedMessagesToSend
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ public class SignalMessagingJobQueues: NSObject {
|
||||
public init(appReadiness: AppReadiness, db: any DB, reachabilityManager: SSKReachabilityManager) {
|
||||
incomingContactSyncJobQueue = IncomingContactSyncJobQueue(appReadiness: appReadiness, db: db, reachabilityManager: reachabilityManager)
|
||||
sessionResetJobQueue = SessionResetJobQueue(db: db, reachabilityManager: reachabilityManager)
|
||||
tsAttachmentMultisendJobQueue = TSAttachmentMultisendJobQueue(db: db, reachabilityManager: reachabilityManager)
|
||||
receiptCredentialJobQueue = DonationReceiptCredentialRedemptionJobQueue(db: db, reachabilityManager: reachabilityManager)
|
||||
sendGiftBadgeJobQueue = SendGiftBadgeJobQueue(db: db, reachabilityManager: reachabilityManager)
|
||||
}
|
||||
@@ -23,7 +22,6 @@ public class SignalMessagingJobQueues: NSObject {
|
||||
// MARK: Swift-only
|
||||
|
||||
public let sessionResetJobQueue: SessionResetJobQueue
|
||||
public let tsAttachmentMultisendJobQueue: TSAttachmentMultisendJobQueue
|
||||
public let receiptCredentialJobQueue: DonationReceiptCredentialRedemptionJobQueue
|
||||
public let sendGiftBadgeJobQueue: SendGiftBadgeJobQueue
|
||||
}
|
||||
|
||||
@@ -206,14 +206,12 @@ CREATE
|
||||
,"failureCount" INTEGER NOT NULL
|
||||
,"label" TEXT NOT NULL
|
||||
,"status" INTEGER NOT NULL
|
||||
,"attachmentIdMap" BLOB
|
||||
,"contactThreadId" TEXT
|
||||
,"envelopeData" BLOB
|
||||
,"invisibleMessage" BLOB
|
||||
,"messageId" TEXT
|
||||
,"removeMessageAfterSending" INTEGER
|
||||
,"threadId" TEXT
|
||||
,"attachmentId" TEXT
|
||||
,"isMediaMessage" BOOLEAN
|
||||
,"serverDeliveryTimestamp" INTEGER
|
||||
,"exclusiveProcessIdentifier" TEXT
|
||||
@@ -228,7 +226,6 @@ CREATE
|
||||
,"receiptCredentialPresentation" BLOB
|
||||
,"amount" NUMERIC
|
||||
,"currencyCode" TEXT
|
||||
,"unsavedMessagesToSend" BLOB
|
||||
,"messageText" TEXT
|
||||
,"paymentIntentClientSecret" TEXT
|
||||
,"paymentMethodId" TEXT
|
||||
|
||||
@@ -259,7 +259,6 @@ public class SSKEnvironment: NSObject {
|
||||
self.localUserLeaveGroupJobQueueRef.start(appContext: CurrentAppContext())
|
||||
self.callRecordDeleteAllJobQueueRef.start(appContext: CurrentAppContext())
|
||||
self.bulkDeleteInteractionJobQueueRef.start(appContext: CurrentAppContext())
|
||||
self.smJobQueuesRef.tsAttachmentMultisendJobQueue.start(appContext: CurrentAppContext())
|
||||
self.smJobQueuesRef.incomingContactSyncJobQueue.start(appContext: CurrentAppContext())
|
||||
self.smJobQueuesRef.receiptCredentialJobQueue.start(appContext: CurrentAppContext())
|
||||
self.smJobQueuesRef.sendGiftBadgeJobQueue.start(appContext: CurrentAppContext())
|
||||
|
||||
@@ -312,6 +312,7 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
case tsMessageAttachmentMigration3
|
||||
case addEditStateToMessageAttachmentReference
|
||||
case removeVersionedDMTimerCapabilities
|
||||
case removeJobRecordTSAttachmentColumns
|
||||
|
||||
// NOTE: Every time we add a migration id, consider
|
||||
// incrementing grdbSchemaVersionLatest.
|
||||
@@ -373,7 +374,7 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
}
|
||||
|
||||
public static let grdbSchemaVersionDefault: UInt = 0
|
||||
public static let grdbSchemaVersionLatest: UInt = 102
|
||||
public static let grdbSchemaVersionLatest: UInt = 103
|
||||
|
||||
// An optimization for new users, we have the first migration import the latest schema
|
||||
// and mark any other migrations as "already run".
|
||||
@@ -3747,6 +3748,19 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
return .success(())
|
||||
}
|
||||
|
||||
migrator.registerMigration(.removeJobRecordTSAttachmentColumns) { tx in
|
||||
// Remove TSAttachmentMultisend records.
|
||||
try tx.database.execute(sql: """
|
||||
DELETE FROM model_SSKJobRecord WHERE recordType = 58;
|
||||
""")
|
||||
try tx.database.alter(table: "model_SSKJobRecord") { table in
|
||||
table.drop(column: "attachmentId")
|
||||
table.drop(column: "attachmentIdMap")
|
||||
table.drop(column: "unsavedMessagesToSend")
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
// MARK: - Schema Migration Insertion Point
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ public enum SDSRecordType: UInt, CaseIterable {
|
||||
case experienceUpgrade = 55
|
||||
case baseModel = 56
|
||||
case contactQuery = 57
|
||||
case tsAttachmentMultisendJobRecord = 58
|
||||
case testModel = 59
|
||||
case incomingGroupSyncJobRecord = 60
|
||||
case incomingContactSyncJobRecord = 61
|
||||
|
||||
@@ -16,7 +16,6 @@ class JobRecordTest: XCTestCase {
|
||||
forRecordType recordType: JobRecord.JobRecordType
|
||||
) -> any (JobRecord & ValidatableModel).Type {
|
||||
switch recordType {
|
||||
case .tsAttachmentMultisend: return TSAttachmentMultisendJobRecord.self
|
||||
case .incomingContactSync: return IncomingContactSyncJobRecord.self
|
||||
case .legacyMessageDecrypt: return LegacyMessageDecryptJobRecord.self
|
||||
case .localUserLeaveGroup: return LocalUserLeaveGroupJobRecord.self
|
||||
@@ -125,45 +124,15 @@ extension ValidatableModel where Self: JobRecord {
|
||||
|
||||
// MARK: - Job records
|
||||
|
||||
extension TSAttachmentMultisendJobRecord: ValidatableModel {
|
||||
static let constants: [(TSAttachmentMultisendJobRecord, jsonData: Data)] = [
|
||||
(
|
||||
TSAttachmentMultisendJobRecord(
|
||||
attachmentIdMap: ["once": ["upon", "a"]],
|
||||
// The encoded object below has a non-story message, which is invalid in the real app.
|
||||
storyMessagesToSend: [],
|
||||
failureCount: 3,
|
||||
status: .running
|
||||
),
|
||||
Data(#"{"super":{"failureCount":3,"label":"BroadcastMediaMessage","status":2,"uniqueId":"F5B3380C-B4DB-45DE-BB07-CC6BCAE97FDB","recordType":58},"attachmentIdMap":"YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGoCwwVFhscHSNVJG51bGzTDQ4PEBIUV05TLmtleXNaTlMub2JqZWN0c1YkY2xhc3OhEYACoROAA4AHVG9uY2XSDg8XGqIYGYAEgAWABlR1cG9uUWHSHh8gIVokY2xhc3NuYW1lWCRjbGFzc2VzV05TQXJyYXmiICJYTlNPYmplY3TSHh8kJVxOU0RpY3Rpb25hcnmiJiJcTlNEaWN0aW9uYXJ5CBEaJCkyN0lMUVNcYmlxfIOFh4mLjZKXmpyeoKWnrLfAyMvU2ebpAAAAAAAAAQEAAAAAAAAAJwAAAAAAAAAAAAAAAAAAAPY=","unsavedMessagesToSend":"YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGqCwwSRkdISUpLV1UkbnVsbNINDg8RWk5TLm9iamVjdHNWJGNsYXNzoRCAAoAJ3xAaExQVFg4XGBkaGxwdHh8gISIjJCUmJygpKissLS0sMC0sMy0sLSwsLCwtLSwtLCxBQiwtLV8QE3JlY2VpdmVkQXRUaW1lc3RhbXBfEBJpc1ZpZXdPbmNlQ29tcGxldGVfEBxzdG9yZWRTaG91bGRTdGFydEV4cGlyZVRpbWVyXxAPZXhwaXJlU3RhcnRlZEF0XxARaXNWaWV3T25jZU1lc3NhZ2VfEA9NVExNb2RlbFZlcnNpb25edW5pcXVlVGhyZWFkSWRfEBVoYXNMZWdhY3lNZXNzYWdlU3RhdGVWc29ydElkXxASaXNGcm9tTGlua2VkRGV2aWNlXxAcb3V0Z29pbmdNZXNzYWdlU2NoZW1hVmVyc2lvbl8QEGV4cGlyZXNJblNlY29uZHNfEBBncm91cE1ldGFNZXNzYWdlXxASbGVnYWN5TWVzc2FnZVN0YXRlXxASbGVnYWN5V2FzRGVsaXZlcmVkXmlzVm9pY2VNZXNzYWdlWWV4cGlyZXNBdF8QEWlzR3JvdXBTdG9yeVJlcGx5XXNjaGVtYVZlcnNpb25ZZWRpdFN0YXRlWXRpbWVzdGFtcFh1bmlxdWVJZF8QEnN0b3JlZE1lc3NhZ2VTdGF0ZV8QEndhc1JlbW90ZWx5RGVsZXRlZF8QE2hhc1N5bmNlZFRyYW5zY3JpcHSAA4AEgASAA4AIgASAA4AFgASAA4AEgAOAA4ADgAOABIAEgAOABIADgAOAB4AGgAOABIAEEAAIW2luIGEgZ2FsYXh5VHRpbWUTAAABjDc01WXSTE1OT1okY2xhc3NuYW1lWCRjbGFzc2VzXxARVFNPdXRnb2luZ01lc3NhZ2WnUFFSU1RVVl8QEVRTT3V0Z29pbmdNZXNzYWdlWVRTTWVzc2FnZV1UU0ludGVyYWN0aW9uWUJhc2VNb2RlbF8QE1RTWWFwRGF0YWJhc2VPYmplY3RYTVRMTW9kZWxYTlNPYmplY3TSTE1YWVdOU0FycmF5olhWAAgAEQAaACQAKQAyADcASQBMAFEAUwBeAGQAaQB0AHsAfQB\/AIEAuADOAOMBAgEUASgBOgFJAWEBaAF9AZwBrwHCAdcB7AH7AgUCGQInAjECOwJEAlkCbgKEAoYCiAKKAowCjgKQApIClAKWApgCmgKcAp4CoAKiAqQCpgKoAqoCrAKuArACsgK0ArYCuAK6ArsCxwLMAtUC2gLlAu4DAgMKAx4DKAM2A0ADVgNfA2gDbQN1AAAAAAAAAgEAAAAAAAAAWgAAAAAAAAAAAAAAAAAAA3g="}"#.utf8)
|
||||
),
|
||||
(
|
||||
TSAttachmentMultisendJobRecord(
|
||||
attachmentIdMap: ["once": ["upon", "a"]],
|
||||
storyMessagesToSend: nil,
|
||||
failureCount: 3,
|
||||
status: .running
|
||||
),
|
||||
Data(#"{"super":{"failureCount":3,"label":"BroadcastMediaMessage","status":2,"uniqueId":"3EB90435-904A-46DA-951D-AF577B38ADD7","recordType":58},"attachmentIdMap":"YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGoCwwVFhscHSNVJG51bGzTDQ4PEBIUV05TLmtleXNaTlMub2JqZWN0c1YkY2xhc3OhEYACoROAA4AHVG9uY2XSDg8XGqIYGYAEgAWABlR1cG9uUWHSHh8gIVokY2xhc3NuYW1lWCRjbGFzc2VzV05TQXJyYXmiICJYTlNPYmplY3TSHh8kJVxOU0RpY3Rpb25hcnmiJiJcTlNEaWN0aW9uYXJ5CBEaJCkyN0lMUVNcYmlxfIOFh4mLjZKXmpyeoKWnrLfAyMvU2ebpAAAAAAAAAQEAAAAAAAAAJwAAAAAAAAAAAAAAAAAAAPY="}"#.utf8)
|
||||
)
|
||||
]
|
||||
|
||||
func validate(against: TSAttachmentMultisendJobRecord) throws {
|
||||
guard
|
||||
attachmentIdMap == against.attachmentIdMap,
|
||||
storyMessagesToSend?.count == against.storyMessagesToSend?.count,
|
||||
storyMessagesToSend?.first?.uniqueId == against.storyMessagesToSend?.first?.uniqueId
|
||||
else {
|
||||
throw ValidatableModelError.failedToValidate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension IncomingContactSyncJobRecord: ValidatableModel {
|
||||
static let constants: [(IncomingContactSyncJobRecord, jsonData: Data)] = [
|
||||
(
|
||||
IncomingContactSyncJobRecord.legacy(
|
||||
legacyAttachmentId: "darth revan",
|
||||
IncomingContactSyncJobRecord(
|
||||
cdnNumber: nil,
|
||||
cdnKey: nil,
|
||||
encryptionKey: nil,
|
||||
digest: nil,
|
||||
plaintextLength: nil,
|
||||
isCompleteContactSync: true,
|
||||
failureCount: 12,
|
||||
status: .ready
|
||||
@@ -171,8 +140,12 @@ extension IncomingContactSyncJobRecord: ValidatableModel {
|
||||
Data(#"{"super":{"failureCount":12,"label":"IncomingContactSync","status":1,"uniqueId":"FF3753B3-B1FD-4B4A-96C3-2398EB120136","recordType":61},"isCompleteContactSync":true,"attachmentId":"darth revan"}"#.utf8)
|
||||
),
|
||||
(
|
||||
IncomingContactSyncJobRecord.legacy(
|
||||
legacyAttachmentId: nil,
|
||||
IncomingContactSyncJobRecord(
|
||||
cdnNumber: nil,
|
||||
cdnKey: nil,
|
||||
encryptionKey: nil,
|
||||
digest: nil,
|
||||
plaintextLength: nil,
|
||||
isCompleteContactSync: false,
|
||||
failureCount: 6,
|
||||
status: .permanentlyFailed
|
||||
@@ -201,19 +174,13 @@ extension IncomingContactSyncJobRecord: ValidatableModel {
|
||||
switch (downloadInfo, against.downloadInfo) {
|
||||
case (.invalid, .invalid):
|
||||
break
|
||||
case let (.legacy(lhsId), .legacy(rhsId)):
|
||||
guard
|
||||
lhsId == rhsId
|
||||
else {
|
||||
throw ValidatableModelError.failedToValidate
|
||||
}
|
||||
case let (.transient(lhsInfo), .transient(rhsInfo)):
|
||||
guard
|
||||
lhsInfo == rhsInfo
|
||||
else {
|
||||
throw ValidatableModelError.failedToValidate
|
||||
}
|
||||
case (.invalid, _), (.legacy, _), (.transient, _):
|
||||
case (.invalid, _), (.transient, _):
|
||||
throw ValidatableModelError.failedToValidate
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user