diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m b/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m index be3d5c5f6..bb2b99b42 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIBackup.m @@ -81,6 +81,18 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [AppEnvironment.shared.backupLazyRestore runIfNecessary]; }]]; + [items addObject:[OWSTableItem itemWithTitle:@"Upload 100 CK records" + actionBlock:^{ + [DebugUIBackup uploadCKBatch:100]; + }]]; + [items addObject:[OWSTableItem itemWithTitle:@"Upload 1,000 CK records" + actionBlock:^{ + [DebugUIBackup uploadCKBatch:1000]; + }]]; + [items addObject:[OWSTableItem itemWithTitle:@"Upload 10,000 CK records" + actionBlock:^{ + [DebugUIBackup uploadCKBatch:10000]; + }]]; return [OWSTableSection sectionWithTitle:self.name items:items]; } @@ -221,6 +233,26 @@ NS_ASSUME_NONNULL_BEGIN [self.backup logBackupMetadataCache:OWSPrimaryStorage.sharedManager.newDatabaseConnection]; } ++ (void)uploadCKBatch:(NSUInteger)count +{ + NSMutableArray *records = [NSMutableArray new]; + for (NSUInteger i = 0; i < count; i++) { + NSData *_Nullable data = [Randomness generateRandomBytes:32]; + OWSAssertDebug(data); + NSString *filePath = [OWSFileSystem temporaryFilePathWithFileExtension:@"pdf"]; + BOOL success = [data writeToFile:filePath atomically:YES]; + OWSAssertDebug(success); + + NSString *recipientId = self.tsAccountManager.localNumber; + NSString *recordName = [OWSBackupAPI recordNameForTestFileWithRecipientId:recipientId]; + CKRecord *record = [OWSBackupAPI recordForFileUrl:[NSURL fileURLWithPath:filePath] recordName:recordName]; + [records addObject:record]; + } + [[OWSBackupAPI saveRecordsToCloudObjcWithRecords:records].thenInBackground(^{ + OWSLogVerbose(@"success."); + }) retainUntilComplete]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/util/Backup/OWSBackupAPI.swift b/Signal/src/util/Backup/OWSBackupAPI.swift index f2acd8dbc..27c6c640f 100644 --- a/Signal/src/util/Backup/OWSBackupAPI.swift +++ b/Signal/src/util/Backup/OWSBackupAPI.swift @@ -134,8 +134,23 @@ import PromiseKit } public class func saveRecordsToCloud(records: [CKRecord]) -> Promise { - return saveRecordsToCloud(records: records, - remainingRetries: maxRetries) + + var remainder = records + var promise = Promise.value(()) + // CloudKit's internal limit is 400, but I haven't found a constant for this. + let kMaxBatchSize = 100 + while remainder.count > 0 { + let batch = Array(remainder[0.. Promise in + Logger.verbose("Saved batch: \(batch.count)") + return Promise.value(()) + } + } + return promise } private class func saveRecordsToCloud(records: [CKRecord], @@ -144,7 +159,7 @@ import PromiseKit let recordNames = records.map { (record) in return record.recordID.recordName } - Logger.verbose("recordNames \(recordNames)") + Logger.verbose("recordNames[\(recordNames.count)] \(recordNames[0..<10])...") return Promise { resolver in let saveOperation = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: nil) @@ -173,7 +188,7 @@ import PromiseKit let outcome = outcomeForCloudKitError(error: error, remainingRetries: remainingRetries, - label: "Save Record") + label: "Save Records[\(recordNames.count)]") switch outcome { case .success: resolver.fulfill(())