Rework lazy attachment restore.
This commit is contained in:
parent
3bff89c7ee
commit
f7842dd2aa
|
@ -156,7 +156,7 @@
|
||||||
3496955E219B605E00DCFE74 /* PhotoLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496955B219B605E00DCFE74 /* PhotoLibrary.swift */; };
|
3496955E219B605E00DCFE74 /* PhotoLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496955B219B605E00DCFE74 /* PhotoLibrary.swift */; };
|
||||||
3496956021A2FC8100DCFE74 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3496955F21A2FC8100DCFE74 /* CloudKit.framework */; };
|
3496956021A2FC8100DCFE74 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3496955F21A2FC8100DCFE74 /* CloudKit.framework */; };
|
||||||
3496956E21A301A100DCFE74 /* OWSBackupExportJob.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956221A301A100DCFE74 /* OWSBackupExportJob.m */; };
|
3496956E21A301A100DCFE74 /* OWSBackupExportJob.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956221A301A100DCFE74 /* OWSBackupExportJob.m */; };
|
||||||
3496956F21A301A100DCFE74 /* OWSBackupLazyRestoreJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496956321A301A100DCFE74 /* OWSBackupLazyRestoreJob.swift */; };
|
3496956F21A301A100DCFE74 /* OWSBackupLazyRestore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496956321A301A100DCFE74 /* OWSBackupLazyRestore.swift */; };
|
||||||
3496957021A301A100DCFE74 /* OWSBackupIO.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956521A301A100DCFE74 /* OWSBackupIO.m */; };
|
3496957021A301A100DCFE74 /* OWSBackupIO.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956521A301A100DCFE74 /* OWSBackupIO.m */; };
|
||||||
3496957121A301A100DCFE74 /* OWSBackupImportJob.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956621A301A100DCFE74 /* OWSBackupImportJob.m */; };
|
3496957121A301A100DCFE74 /* OWSBackupImportJob.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956621A301A100DCFE74 /* OWSBackupImportJob.m */; };
|
||||||
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956921A301A100DCFE74 /* OWSBackup.m */; };
|
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496956921A301A100DCFE74 /* OWSBackup.m */; };
|
||||||
|
@ -812,7 +812,7 @@
|
||||||
3496955B219B605E00DCFE74 /* PhotoLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoLibrary.swift; sourceTree = "<group>"; };
|
3496955B219B605E00DCFE74 /* PhotoLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoLibrary.swift; sourceTree = "<group>"; };
|
||||||
3496955F21A2FC8100DCFE74 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
3496955F21A2FC8100DCFE74 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
||||||
3496956221A301A100DCFE74 /* OWSBackupExportJob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupExportJob.m; sourceTree = "<group>"; };
|
3496956221A301A100DCFE74 /* OWSBackupExportJob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupExportJob.m; sourceTree = "<group>"; };
|
||||||
3496956321A301A100DCFE74 /* OWSBackupLazyRestoreJob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSBackupLazyRestoreJob.swift; sourceTree = "<group>"; };
|
3496956321A301A100DCFE74 /* OWSBackupLazyRestore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSBackupLazyRestore.swift; sourceTree = "<group>"; };
|
||||||
3496956421A301A100DCFE74 /* OWSBackup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackup.h; sourceTree = "<group>"; };
|
3496956421A301A100DCFE74 /* OWSBackup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackup.h; sourceTree = "<group>"; };
|
||||||
3496956521A301A100DCFE74 /* OWSBackupIO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupIO.m; sourceTree = "<group>"; };
|
3496956521A301A100DCFE74 /* OWSBackupIO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupIO.m; sourceTree = "<group>"; };
|
||||||
3496956621A301A100DCFE74 /* OWSBackupImportJob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupImportJob.m; sourceTree = "<group>"; };
|
3496956621A301A100DCFE74 /* OWSBackupImportJob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBackupImportJob.m; sourceTree = "<group>"; };
|
||||||
|
@ -1778,7 +1778,7 @@
|
||||||
3496956521A301A100DCFE74 /* OWSBackupIO.m */,
|
3496956521A301A100DCFE74 /* OWSBackupIO.m */,
|
||||||
3496956721A301A100DCFE74 /* OWSBackupJob.h */,
|
3496956721A301A100DCFE74 /* OWSBackupJob.h */,
|
||||||
3496956A21A301A100DCFE74 /* OWSBackupJob.m */,
|
3496956A21A301A100DCFE74 /* OWSBackupJob.m */,
|
||||||
3496956321A301A100DCFE74 /* OWSBackupLazyRestoreJob.swift */,
|
3496956321A301A100DCFE74 /* OWSBackupLazyRestore.swift */,
|
||||||
);
|
);
|
||||||
path = Backup;
|
path = Backup;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3568,7 +3568,7 @@
|
||||||
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */,
|
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */,
|
||||||
B90418E6183E9DD40038554A /* DateUtil.m in Sources */,
|
B90418E6183E9DD40038554A /* DateUtil.m in Sources */,
|
||||||
340FC8BD204DAC8D007AEB0F /* ShowGroupMembersViewController.m in Sources */,
|
340FC8BD204DAC8D007AEB0F /* ShowGroupMembersViewController.m in Sources */,
|
||||||
3496956F21A301A100DCFE74 /* OWSBackupLazyRestoreJob.swift in Sources */,
|
3496956F21A301A100DCFE74 /* OWSBackupLazyRestore.swift in Sources */,
|
||||||
459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */,
|
459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -1212,11 +1212,6 @@ static NSTimeInterval launchStartedAt;
|
||||||
|
|
||||||
[self.messageManager startObserving];
|
[self.messageManager startObserving];
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Resume lazy restore.
|
|
||||||
[OWSBackupLazyRestoreJob runAsync];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[self.udManager setup];
|
[self.udManager setup];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,9 @@ import SignalMessaging
|
||||||
@objc
|
@objc
|
||||||
public var backup: OWSBackup
|
public var backup: OWSBackup
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public var backupLazyRestore: BackupLazyRestore
|
||||||
|
|
||||||
private override init() {
|
private override init() {
|
||||||
self.callMessageHandler = WebRTCCallMessageHandler()
|
self.callMessageHandler = WebRTCCallMessageHandler()
|
||||||
self.callService = CallService()
|
self.callService = CallService()
|
||||||
|
@ -70,6 +73,7 @@ import SignalMessaging
|
||||||
self.pushManager = PushManager()
|
self.pushManager = PushManager()
|
||||||
self.sessionResetJobQueue = SessionResetJobQueue()
|
self.sessionResetJobQueue = SessionResetJobQueue()
|
||||||
self.backup = OWSBackup()
|
self.backup = OWSBackup()
|
||||||
|
self.backupLazyRestore = BackupLazyRestore()
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
|
|
@ -95,9 +95,7 @@ NSError *OWSBackupErrorWithDescription(NSString *description);
|
||||||
|
|
||||||
- (NSArray<NSString *> *)attachmentIdsForLazyRestore;
|
- (NSArray<NSString *> *)attachmentIdsForLazyRestore;
|
||||||
|
|
||||||
- (void)lazyRestoreAttachment:(TSAttachmentPointer *)attachment
|
- (AnyPromise *)lazyRestoreAttachment:(TSAttachmentPointer *)attachment backupIO:(OWSBackupIO *)backupIO;
|
||||||
backupIO:(OWSBackupIO *)backupIO
|
|
||||||
completion:(OWSBackupBoolBlock)completion;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,11 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
|
||||||
return AppEnvironment.shared.backup;
|
return AppEnvironment.shared.backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (OWSBackupLazyRestore *)backupLazyRestore
|
||||||
|
{
|
||||||
|
return AppEnvironment.shared.backupLazyRestore;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
- (NSArray<OWSBackupFragment *> *)databaseItems
|
- (NSArray<OWSBackupFragment *> *)databaseItems
|
||||||
|
@ -157,10 +162,11 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
|
||||||
.thenInBackground(^{
|
.thenInBackground(^{
|
||||||
return [self restoreAttachmentFiles];
|
return [self restoreAttachmentFiles];
|
||||||
})
|
})
|
||||||
|
.then(^{
|
||||||
|
// Kick off lazy restore on main thread.
|
||||||
|
[self.backupLazyRestore runIfNecessary];
|
||||||
|
})
|
||||||
.thenInBackground(^{
|
.thenInBackground(^{
|
||||||
// Kick off lazy restore.
|
|
||||||
[OWSBackupLazyRestoreJob runAsync];
|
|
||||||
|
|
||||||
[self.profileManager fetchLocalUsersProfile];
|
[self.profileManager fetchLocalUsersProfile];
|
||||||
|
|
||||||
[self.tsAccountManager updateAccountAttributes];
|
[self.tsAccountManager updateAccountAttributes];
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import PromiseKit
|
||||||
|
import SignalServiceKit
|
||||||
|
|
||||||
|
@objc(OWSBackupLazyRestore)
|
||||||
|
public class BackupLazyRestore: NSObject {
|
||||||
|
|
||||||
|
// MARK: - Dependencies
|
||||||
|
|
||||||
|
private var backup: OWSBackup {
|
||||||
|
return AppEnvironment.shared.backup
|
||||||
|
}
|
||||||
|
|
||||||
|
private var primaryStorage: OWSPrimaryStorage {
|
||||||
|
return SSKEnvironment.shared.primaryStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
private var tsAccountManager: TSAccountManager {
|
||||||
|
return TSAccountManager.sharedInstance()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
private var isRunning = false
|
||||||
|
private var isComplete = false
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public required override init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
SwiftSingletons.register(self)
|
||||||
|
|
||||||
|
AppReadiness.runNowOrWhenAppDidBecomeReady {
|
||||||
|
self.runIfNecessary()
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(forName: .OWSApplicationDidBecomeActive, object: nil, queue: nil) { _ in
|
||||||
|
self.runIfNecessary()
|
||||||
|
}
|
||||||
|
NotificationCenter.default.addObserver(forName: .RegistrationStateDidChange, object: nil, queue: nil) { _ in
|
||||||
|
self.runIfNecessary()
|
||||||
|
}
|
||||||
|
NotificationCenter.default.addObserver(forName: .reachabilityChanged, object: nil, queue: nil) { _ in
|
||||||
|
self.runIfNecessary()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
private var backgroundQueue = {
|
||||||
|
DispatchQueue.global(qos: .background)
|
||||||
|
}()
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public func runIfNecessary() {
|
||||||
|
AssertIsOnMainThread()
|
||||||
|
|
||||||
|
guard CurrentAppContext().isMainAppAndActive else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard tsAccountManager.isRegisteredAndReady() else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard !isRunning, !isComplete else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning = true
|
||||||
|
|
||||||
|
backgroundQueue.async {
|
||||||
|
self.restoreAttachments()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func restoreAttachments() {
|
||||||
|
let temporaryDirectory = OWSTemporaryDirectory()
|
||||||
|
let jobTempDirPath = (temporaryDirectory as NSString).appendingPathComponent(NSUUID().uuidString)
|
||||||
|
|
||||||
|
guard OWSFileSystem.ensureDirectoryExists(jobTempDirPath) else {
|
||||||
|
Logger.error("could not create temp directory.")
|
||||||
|
complete(errorCount: 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let backupIO = OWSBackupIO(jobTempDirPath: jobTempDirPath)
|
||||||
|
|
||||||
|
let attachmentIds = backup.attachmentIdsForLazyRestore()
|
||||||
|
guard attachmentIds.count > 0 else {
|
||||||
|
Logger.info("No attachments need lazy restore.")
|
||||||
|
complete(errorCount: 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Logger.info("Lazy restoring \(attachmentIds.count) attachments.")
|
||||||
|
tryToRestoreNextAttachment(attachmentIds: attachmentIds, errorCount: 0, backupIO: backupIO)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func tryToRestoreNextAttachment(attachmentIds: [String], errorCount: UInt, backupIO: OWSBackupIO) {
|
||||||
|
var attachmentIdsCopy = attachmentIds
|
||||||
|
guard let attachmentId = attachmentIdsCopy.last else {
|
||||||
|
// This job is done.
|
||||||
|
Logger.verbose("job is done.")
|
||||||
|
complete(errorCount: errorCount)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
attachmentIdsCopy.removeLast()
|
||||||
|
guard let attachmentPointer = TSAttachment.fetch(uniqueId: attachmentId) as? TSAttachmentPointer else {
|
||||||
|
Logger.warn("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, errorCount: errorCount + 1, backupIO: backupIO)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
backup.lazyRestoreAttachment(attachmentPointer,
|
||||||
|
backupIO: backupIO)
|
||||||
|
.done { _ in
|
||||||
|
Logger.info("Restored attachment.")
|
||||||
|
|
||||||
|
self.backgroundQueue.async {
|
||||||
|
// Continue trying to restore the other attachments.
|
||||||
|
self.tryToRestoreNextAttachment(attachmentIds: attachmentIdsCopy, errorCount: errorCount, backupIO: backupIO)
|
||||||
|
}
|
||||||
|
}.catch { (error) in
|
||||||
|
Logger.error("Could not restore attachment: \(error)")
|
||||||
|
|
||||||
|
self.backgroundQueue.async {
|
||||||
|
// Continue trying to restore the other attachments.
|
||||||
|
self.tryToRestoreNextAttachment(attachmentIds: attachmentIdsCopy, errorCount: errorCount + 1, backupIO: backupIO)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func complete(errorCount: UInt) {
|
||||||
|
Logger.verbose("")
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.isRunning = false
|
||||||
|
|
||||||
|
if errorCount == 0 {
|
||||||
|
self.isComplete = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,92 +0,0 @@
|
||||||
//
|
|
||||||
// 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() {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
|
|
||||||
DispatchQueue.global().async {
|
|
||||||
self.restoreAttachments()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func restoreAttachments() {
|
|
||||||
let temporaryDirectory = OWSTemporaryDirectory()
|
|
||||||
let jobTempDirPath = (temporaryDirectory as NSString).appendingPathComponent(NSUUID().uuidString)
|
|
||||||
|
|
||||||
guard OWSFileSystem.ensureDirectoryExists(jobTempDirPath) else {
|
|
||||||
Logger.error("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("No attachments need lazy restore.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Logger.info("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("job is done.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
attachmentIdsCopy.removeLast()
|
|
||||||
guard let attachmentPointer = TSAttachment.fetch(uniqueId: attachmentId) as? TSAttachmentPointer else {
|
|
||||||
Logger.warn("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(attachmentPointer,
|
|
||||||
backupIO: backupIO,
|
|
||||||
completion: { (success) in
|
|
||||||
if success {
|
|
||||||
Logger.info("restored attachment.")
|
|
||||||
} else {
|
|
||||||
Logger.warn("could not restore attachment.")
|
|
||||||
}
|
|
||||||
// Continue trying to restore the other attachments.
|
|
||||||
self.tryToRestoreNextAttachment(attachmentIds: attachmentIdsCopy, backupIO: backupIO)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue