From fe8259bf0ce1b64f3b8c77e5e1e2b3b244416799 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 30 Nov 2018 12:05:18 -0500 Subject: [PATCH 1/5] Fix incremental backup exports. --- .../ViewControllers/DebugUI/DebugUIBackup.m | 13 ++++++-- Signal/src/util/Backup/OWSBackup.h | 3 ++ Signal/src/util/Backup/OWSBackup.m | 21 ++++++++++++ Signal/src/util/Backup/OWSBackupExportJob.m | 33 +++++++++++-------- Signal/src/util/Backup/OWSBackupIO.m | 4 +++ Signal/src/util/Backup/OWSBackupImportJob.m | 17 ++++------ Signal/src/util/Backup/OWSBackupJob.m | 2 +- .../Attachments/OWSAttachmentDownloads.m | 1 - .../Attachments/TSAttachmentPointer.m | 5 ++- SignalServiceKit/src/Util/OWSBackupFragment.h | 3 ++ SignalServiceKit/src/Util/OWSBackupFragment.m | 12 +++---- 11 files changed, 79 insertions(+), 35 deletions(-) diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m b/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m index 0c6b49848..df3c14543 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m @@ -73,6 +73,10 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [DebugUIBackup clearBackupMetadataCache]; }]]; + [items addObject:[OWSTableItem itemWithTitle:@"Log Backup Metadata Cache" + actionBlock:^{ + [DebugUIBackup logBackupMetadataCache]; + }]]; return [OWSTableSection sectionWithTitle:self.name items:items]; } @@ -191,14 +195,14 @@ NS_ASSUME_NONNULL_BEGIN + (void)clearAllCloudKitRecords { - OWSLogInfo(@"clearAllCloudKitRecords."); + OWSLogInfo(@""); [OWSBackup.sharedManager clearAllCloudKitRecords]; } + (void)clearBackupMetadataCache { - OWSLogInfo(@"ClearBackupMetadataCache."); + OWSLogInfo(@""); [OWSPrimaryStorage.sharedManager.newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { @@ -206,6 +210,11 @@ NS_ASSUME_NONNULL_BEGIN }]; } ++ (void)logBackupMetadataCache +{ + [self.backup logBackupMetadataCache:OWSPrimaryStorage.sharedManager.newDatabaseConnection]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/util/Backup/OWSBackup.h b/Signal/src/util/Backup/OWSBackup.h index b1b235edf..0eabc15e3 100644 --- a/Signal/src/util/Backup/OWSBackup.h +++ b/Signal/src/util/Backup/OWSBackup.h @@ -32,6 +32,7 @@ NSError *OWSBackupErrorWithDescription(NSString *description); @class OWSBackupIO; @class TSAttachmentPointer; @class TSThread; +@class YapDatabaseConnection; @interface OWSBackup : NSObject @@ -91,6 +92,8 @@ NSError *OWSBackupErrorWithDescription(NSString *description); - (void)logBackupRecords; - (void)clearAllCloudKitRecords; +- (void)logBackupMetadataCache:(YapDatabaseConnection *)dbConnection; + #pragma mark - Lazy Restore - (NSArray *)attachmentRecordNamesForLazyRestore; diff --git a/Signal/src/util/Backup/OWSBackup.m b/Signal/src/util/Backup/OWSBackup.m index 68699580c..61eedf744 100644 --- a/Signal/src/util/Backup/OWSBackup.m +++ b/Signal/src/util/Backup/OWSBackup.m @@ -866,6 +866,27 @@ NSError *OWSBackupErrorWithDescription(NSString *description) return [AnyPromise promiseWithValue:@(1)]; } +- (void)logBackupMetadataCache:(YapDatabaseConnection *)dbConnection +{ + OWSLogInfo(@""); + + [dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + [transaction enumerateKeysAndObjectsInCollection:[OWSBackupFragment collection] + usingBlock:^(NSString *key, OWSBackupFragment *fragment, BOOL *stop) { + OWSLogVerbose(@"fragment: %@, %@, %lu, %@, %@, %@, %@", + key, + fragment.recordName, + (unsigned long)fragment.encryptionKey.length, + fragment.relativeFilePath, + fragment.attachmentId, + fragment.downloadFilePath, + fragment.uncompressedDataLength); + }]; + OWSLogVerbose(@"Number of fragments: %lu", + (unsigned long)[transaction numberOfKeysInCollection:[OWSBackupFragment collection]]); + }]; +} + #pragma mark - Notifications - (void)postDidChangeNotification diff --git a/Signal/src/util/Backup/OWSBackupExportJob.m b/Signal/src/util/Backup/OWSBackupExportJob.m index d1524035b..2e6ae49a4 100644 --- a/Signal/src/util/Backup/OWSBackupExportJob.m +++ b/Signal/src/util/Backup/OWSBackupExportJob.m @@ -315,6 +315,8 @@ NS_ASSUME_NONNULL_BEGIN // If we are replacing an existing backup, we use some of its contents for continuity. @property (nonatomic, nullable) NSSet *lastValidRecordNames; +@property (nonatomic, nullable) YapDatabaseConnection *dbConnection; + @end #pragma mark - @@ -354,6 +356,8 @@ NS_ASSUME_NONNULL_BEGIN [self updateProgressWithDescription:nil progress:nil]; + self.dbConnection = self.primaryStorage.newDatabaseConnection; + [[self.backup ensureCloudKitAccess] .thenInBackground(^{ [self updateProgressWithDescription:NSLocalizedString(@"BACKUP_EXPORT_PHASE_CONFIGURATION", @@ -379,6 +383,8 @@ NS_ASSUME_NONNULL_BEGIN return [self cleanUp]; }) .thenInBackground(^{ + [self.backup logBackupMetadataCache:self.dbConnection]; + [self succeed]; }) .catch(^(NSError *error) { @@ -479,12 +485,6 @@ NS_ASSUME_NONNULL_BEGIN @"Indicates that the database data is being exported.") progress:nil]; - YapDatabaseConnection *_Nullable dbConnection = self.primaryStorage.newDatabaseConnection; - if (!dbConnection) { - OWSFailDebug(@"Could not create dbConnection."); - return NO; - } - OWSDBExportStream *exportStream = [[OWSDBExportStream alloc] initWithBackupIO:self.backupIO]; __block BOOL aborted = NO; @@ -548,7 +548,7 @@ NS_ASSUME_NONNULL_BEGIN __block NSUInteger copiedMigrations = 0; __block NSUInteger copiedMisc = 0; self.unsavedAttachmentExports = [NSMutableArray new]; - [dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { copiedThreads = exportEntities(transaction, [TSThread collection], [TSThread class], @@ -570,10 +570,9 @@ NS_ASSUME_NONNULL_BEGIN } TSAttachmentStream *attachmentStream = object; NSString *_Nullable filePath = attachmentStream.originalFilePath; - if (!filePath) { - OWSLogError(@"attachment is missing file."); + if (!filePath || ![NSFileManager.defaultManager fileExistsAtPath:filePath]) { + OWSFailDebug(@"attachment is missing file."); return NO; - OWSAssertDebug(attachmentStream.uniqueId.length > 0); } // OWSAttachmentExport is used to lazily write an encrypted copy of the @@ -866,13 +865,17 @@ NS_ASSUME_NONNULL_BEGIN [self.savedAttachmentItems addObject:exportItem]; // Immediately save the record metadata to facilitate export resume. - OWSBackupFragment *backupFragment = [OWSBackupFragment new]; + OWSBackupFragment *backupFragment = [[OWSBackupFragment alloc] initWithUniqueId:recordName]; backupFragment.recordName = recordName; backupFragment.encryptionKey = exportItem.encryptedItem.encryptionKey; backupFragment.relativeFilePath = attachmentExport.relativeFilePath; backupFragment.attachmentId = attachmentExport.attachmentId; backupFragment.uncompressedDataLength = exportItem.uncompressedDataLength; - [backupFragment save]; + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [backupFragment saveWithTransaction:transaction]; + }]; + + [self.backup logBackupMetadataCache:self.dbConnection]; OWSLogVerbose( @"saved attachment: %@ as %@", attachmentExport.attachmentFilePath, attachmentExport.relativeFilePath); @@ -1064,9 +1067,11 @@ NS_ASSUME_NONNULL_BEGIN // After every successful backup export, we can (and should) cull metadata // for any backup fragment (i.e. CloudKit record) that wasn't involved in // the latest backup export. - [self.primaryStorage.newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + NSArray *allRecordNames = [transaction allKeysInCollection:[OWSBackupFragment collection]]; + NSMutableSet *obsoleteRecordNames = [NSMutableSet new]; - [obsoleteRecordNames addObjectsFromArray:[transaction allKeysInCollection:[OWSBackupFragment collection]]]; + [obsoleteRecordNames addObjectsFromArray:allRecordNames]; [obsoleteRecordNames minusSet:activeRecordNames]; [transaction removeObjectsForKeys:obsoleteRecordNames.allObjects inCollection:[OWSBackupFragment collection]]; diff --git a/Signal/src/util/Backup/OWSBackupIO.m b/Signal/src/util/Backup/OWSBackupIO.m index 1b3b6c104..14c903c3e 100644 --- a/Signal/src/util/Backup/OWSBackupIO.m +++ b/Signal/src/util/Backup/OWSBackupIO.m @@ -76,6 +76,10 @@ static const compression_algorithm SignalCompressionAlgorithm = COMPRESSION_LZMA OWSAssertDebug(encryptionKey.length > 0); @autoreleasepool { + if (![[NSFileManager defaultManager] fileExistsAtPath:srcFilePath]) { + OWSFailDebug(@"Missing source file."); + return nil; + } // TODO: Encrypt the file without loading it into memory. NSData *_Nullable srcData = [NSData dataWithContentsOfFile:srcFilePath]; diff --git a/Signal/src/util/Backup/OWSBackupImportJob.m b/Signal/src/util/Backup/OWSBackupImportJob.m index 201d1439c..8bc7746da 100644 --- a/Signal/src/util/Backup/OWSBackupImportJob.m +++ b/Signal/src/util/Backup/OWSBackupImportJob.m @@ -29,6 +29,8 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe @property (nonatomic) OWSBackupManifestContents *manifest; +@property (nonatomic, nullable) YapDatabaseConnection *dbConnection; + @end #pragma mark - @@ -92,6 +94,8 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe self.backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__]; + self.dbConnection = self.primaryStorage.newDatabaseConnection; + [self updateProgressWithDescription:nil progress:nil]; [[self.backup ensureCloudKitAccess] @@ -150,7 +154,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe [allItems addObjectsFromArray:self.attachmentsItems]; // Record metadata for all items, so that we can re-use them in incremental backups after the restore. - [self.primaryStorage.newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { for (OWSBackupFragment *item in allItems) { [item saveWithTransaction:transaction]; } @@ -324,8 +328,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe } __block NSUInteger count = 0; - YapDatabaseConnection *dbConnection = self.primaryStorage.newDatabaseConnection; - [dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { for (OWSBackupFragment *item in self.attachmentsItems) { if (self.isComplete) { return; @@ -379,12 +382,6 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Backup import no longer active.")]; } - YapDatabaseConnection *_Nullable dbConnection = self.primaryStorage.newDatabaseConnection; - if (!dbConnection) { - OWSFailDebug(@"Could not create dbConnection."); - return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Could not create dbConnection.")]; - } - // Order matters here. NSArray *collectionsToRestore = @[ [TSThread collection], @@ -397,7 +394,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe NSMutableDictionary *restoredEntityCounts = [NSMutableDictionary new]; __block unsigned long long copiedEntities = 0; __block BOOL aborted = NO; - [dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { for (NSString *collection in collectionsToRestore) { if ([collection isEqualToString:[OWSDatabaseMigration collection]]) { // It's okay if there are existing migrations; we'll clear those diff --git a/Signal/src/util/Backup/OWSBackupJob.m b/Signal/src/util/Backup/OWSBackupJob.m index 759b451ea..58b008bca 100644 --- a/Signal/src/util/Backup/OWSBackupJob.m +++ b/Signal/src/util/Backup/OWSBackupJob.m @@ -300,7 +300,7 @@ NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService"; return nil; } - OWSBackupFragment *item = [OWSBackupFragment new]; + OWSBackupFragment *item = [[OWSBackupFragment alloc] initWithUniqueId:recordName]; item.recordName = recordName; item.encryptionKey = encryptionKey; item.relativeFilePath = relativeFilePath; diff --git a/SignalServiceKit/src/Messages/Attachments/OWSAttachmentDownloads.m b/SignalServiceKit/src/Messages/Attachments/OWSAttachmentDownloads.m index fc855804a..4ca391c61 100644 --- a/SignalServiceKit/src/Messages/Attachments/OWSAttachmentDownloads.m +++ b/SignalServiceKit/src/Messages/Attachments/OWSAttachmentDownloads.m @@ -186,7 +186,6 @@ typedef void (^AttachmentDownloadFailure)(NSError *error); failure:(void (^)(NSError *error))failureHandler { OWSAssertDebug(attachmentStreamsParam); - OWSAssertDebug(attachmentPointers.count > 0); // To avoid deadlocks, synchronize on self outside of the transaction. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m index 1fc16e38d..2d9927309 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m @@ -183,7 +183,10 @@ NS_ASSUME_NONNULL_BEGIN if (!self.lazyRestoreFragmentId) { return nil; } - return [OWSBackupFragment fetchObjectWithUniqueID:self.lazyRestoreFragmentId]; + OWSBackupFragment *_Nullable backupFragment = + [OWSBackupFragment fetchObjectWithUniqueID:self.lazyRestoreFragmentId]; + OWSAssertDebug(backupFragment); + return backupFragment; } #pragma mark - Update With... Methods diff --git a/SignalServiceKit/src/Util/OWSBackupFragment.h b/SignalServiceKit/src/Util/OWSBackupFragment.h index 6db141c00..8b3dbd03b 100644 --- a/SignalServiceKit/src/Util/OWSBackupFragment.h +++ b/SignalServiceKit/src/Util/OWSBackupFragment.h @@ -37,6 +37,9 @@ NS_ASSUME_NONNULL_BEGIN // This property is only set if the manifest item is compressed. @property (nonatomic, nullable) NSNumber *uncompressedDataLength; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_DESIGNATED_INITIALIZER; + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Util/OWSBackupFragment.m b/SignalServiceKit/src/Util/OWSBackupFragment.m index e38c42a93..f88f8773d 100644 --- a/SignalServiceKit/src/Util/OWSBackupFragment.m +++ b/SignalServiceKit/src/Util/OWSBackupFragment.m @@ -8,14 +8,14 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSBackupFragment -- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction +- (instancetype)initWithUniqueId:(NSString *)uniqueId { - OWSAssertDebug(self.recordName.length > 0); - - if (!self.uniqueId) { - self.uniqueId = self.recordName; + self = [super initWithUniqueId:uniqueId]; + if (!self) { + return self; } - [super saveWithTransaction:transaction]; + + return self; } @end From 9a123d8ce91411f8c6ec22ea5fdd8086c6d98c9d Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 30 Nov 2018 12:35:49 -0500 Subject: [PATCH 2/5] Fix incremental backup exports. --- Signal/src/ViewControllers/DebugUI/DebugUIBackup.m | 4 ++++ Signal/src/util/Backup/OWSBackupImportJob.m | 2 +- Signal/src/util/Backup/OWSBackupLazyRestore.swift | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m b/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m index df3c14543..0f291c8fa 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m @@ -77,6 +77,10 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [DebugUIBackup logBackupMetadataCache]; }]]; + [items addObject:[OWSTableItem itemWithTitle:@"Lazy Restore Attachments" + actionBlock:^{ + [AppEnvironment.shared.backupLazyRestore runIfNecessary]; + }]]; return [OWSTableSection sectionWithTitle:self.name items:items]; } diff --git a/Signal/src/util/Backup/OWSBackupImportJob.m b/Signal/src/util/Backup/OWSBackupImportJob.m index 8bc7746da..a11186505 100644 --- a/Signal/src/util/Backup/OWSBackupImportJob.m +++ b/Signal/src/util/Backup/OWSBackupImportJob.m @@ -175,7 +175,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe }) .then(^{ // Kick off lazy restore on main thread. - [self.backupLazyRestore runIfNecessary]; + [self.backupLazyRestore clearCompleteAndRunIfNecessary]; [self.profileManager fetchLocalUsersProfile]; diff --git a/Signal/src/util/Backup/OWSBackupLazyRestore.swift b/Signal/src/util/Backup/OWSBackupLazyRestore.swift index 563c266cb..149dfa48f 100644 --- a/Signal/src/util/Backup/OWSBackupLazyRestore.swift +++ b/Signal/src/util/Backup/OWSBackupLazyRestore.swift @@ -53,6 +53,15 @@ public class BackupLazyRestore: NSObject { private let backgroundQueue = DispatchQueue.global(qos: .background) + @objc + public func clearCompleteAndRunIfNecessary() { + AssertIsOnMainThread() + + isComplete = false + + runIfNecessary() + } + @objc public func runIfNecessary() { AssertIsOnMainThread() From e26eb5459a9efc2235c811abf70bbacf0c02f5bd Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 30 Nov 2018 12:37:29 -0500 Subject: [PATCH 3/5] Fix incremental backup exports. --- Signal/src/util/Backup/OWSBackupExportJob.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/Signal/src/util/Backup/OWSBackupExportJob.m b/Signal/src/util/Backup/OWSBackupExportJob.m index 2e6ae49a4..1cda8fb9d 100644 --- a/Signal/src/util/Backup/OWSBackupExportJob.m +++ b/Signal/src/util/Backup/OWSBackupExportJob.m @@ -383,8 +383,6 @@ NS_ASSUME_NONNULL_BEGIN return [self cleanUp]; }) .thenInBackground(^{ - [self.backup logBackupMetadataCache:self.dbConnection]; - [self succeed]; }) .catch(^(NSError *error) { From f6b5a9eecc336a9578ba41a66dd9c273ebb1c97c Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 30 Nov 2018 12:42:15 -0500 Subject: [PATCH 4/5] Fix incremental backup exports. --- Signal/src/util/Backup/OWSBackupExportJob.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/Signal/src/util/Backup/OWSBackupExportJob.m b/Signal/src/util/Backup/OWSBackupExportJob.m index 1cda8fb9d..845885aa5 100644 --- a/Signal/src/util/Backup/OWSBackupExportJob.m +++ b/Signal/src/util/Backup/OWSBackupExportJob.m @@ -873,8 +873,6 @@ NS_ASSUME_NONNULL_BEGIN [backupFragment saveWithTransaction:transaction]; }]; - [self.backup logBackupMetadataCache:self.dbConnection]; - OWSLogVerbose( @"saved attachment: %@ as %@", attachmentExport.attachmentFilePath, attachmentExport.relativeFilePath); }) From 7506d93eaf3c70e343640c02f8f3eea865f80ad3 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 3 Dec 2018 22:41:08 -0500 Subject: [PATCH 5/5] Respond to CR. --- SignalServiceKit/src/Util/OWSBackupFragment.h | 1 - SignalServiceKit/src/Util/OWSBackupFragment.m | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/SignalServiceKit/src/Util/OWSBackupFragment.h b/SignalServiceKit/src/Util/OWSBackupFragment.h index 8b3dbd03b..3acddd799 100644 --- a/SignalServiceKit/src/Util/OWSBackupFragment.h +++ b/SignalServiceKit/src/Util/OWSBackupFragment.h @@ -38,7 +38,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable) NSNumber *uncompressedDataLength; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithUniqueId:(NSString *)uniqueId NS_DESIGNATED_INITIALIZER; @end diff --git a/SignalServiceKit/src/Util/OWSBackupFragment.m b/SignalServiceKit/src/Util/OWSBackupFragment.m index f88f8773d..87627f26f 100644 --- a/SignalServiceKit/src/Util/OWSBackupFragment.m +++ b/SignalServiceKit/src/Util/OWSBackupFragment.m @@ -8,16 +8,6 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSBackupFragment -- (instancetype)initWithUniqueId:(NSString *)uniqueId -{ - self = [super initWithUniqueId:uniqueId]; - if (!self) { - return self; - } - - return self; -} - @end NS_ASSUME_NONNULL_END