// // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation import PromiseKit import SignalServiceKit @objc public class OWSBackupLazyRestoreJob: NSObject { let primaryStorage: OWSPrimaryStorage private var jobTempDirPath: String? deinit { if let jobTempDirPath = self.jobTempDirPath { DispatchQueue.global().async { OWSFileSystem.deleteFile(jobTempDirPath) } } } @objc public class func runAsync() { OWSBackupLazyRestoreJob().runAsync() } public override init() { self.primaryStorage = OWSPrimaryStorage.shared() } private func runAsync() { SwiftAssertIsOnMainThread(#function) DispatchQueue.global().async { self.restoreAttachments() } } private func restoreAttachments() { let temporaryDirectory = NSTemporaryDirectory() let jobTempDirPath = (temporaryDirectory as NSString).appendingPathComponent(NSUUID().uuidString) guard OWSFileSystem.ensureDirectoryExists(jobTempDirPath) else { Logger.error("\(logTag) could not create temp directory.") return } self.jobTempDirPath = jobTempDirPath let backupIO = OWSBackupIO(jobTempDirPath: jobTempDirPath) let attachmentIds = OWSBackup.shared().attachmentIdsForLazyRestore() guard attachmentIds.count > 0 else { Logger.info("\(logTag) No attachments need lazy restore.") return } Logger.info("\(logTag) Lazy restoring \(attachmentIds.count) attachments.") self.tryToRestoreNextAttachment(attachmentIds: attachmentIds, backupIO: backupIO) } private func tryToRestoreNextAttachment(attachmentIds: [String], backupIO: OWSBackupIO) { var attachmentIdsCopy = attachmentIds guard let attachmentId = attachmentIdsCopy.last else { // This job is done. Logger.verbose("\(logTag) job is done.") return } attachmentIdsCopy.removeLast() guard let attachment = TSAttachmentStream.fetch(uniqueId: attachmentId) else { Logger.warn("\(logTag) could not load attachment.") // Not necessarily an error. // The attachment might have been deleted since the job began. // Continue trying to restore the other attachments. tryToRestoreNextAttachment(attachmentIds: attachmentIds, backupIO: backupIO) return } OWSBackup.shared().lazyRestoreAttachment(attachment, backupIO: backupIO, completion: { (success) in if success { Logger.info("\(self.logTag) restored attachment.") } else { Logger.warn("\(self.logTag) could not restore attachment.") } // Continue trying to restore the other attachments. self.tryToRestoreNextAttachment(attachmentIds: attachmentIdsCopy, backupIO: backupIO) }) } }