Cancel quickly if dependent operation fails
This commit is contained in:
parent
90214ae578
commit
eb4c62593b
|
@ -5,7 +5,7 @@
|
|||
import Foundation
|
||||
|
||||
@objc(OWSContactDiscoveryOperation)
|
||||
class ContactDiscoveryOperation: OWSOperation {
|
||||
class ContactDiscoveryOperation: OWSOperation, LegacyContactDiscoveryBatchOperationDelegate {
|
||||
|
||||
let batchSize = 2048
|
||||
let recipientIdsToLookup: [String]
|
||||
|
@ -23,6 +23,7 @@ class ContactDiscoveryOperation: OWSOperation {
|
|||
Logger.debug("\(logTag) in \(#function) with recipientIdsToLookup: \(recipientIdsToLookup.count)")
|
||||
for batchIds in recipientIdsToLookup.chunked(by: batchSize) {
|
||||
let batchOperation = LegacyContactDiscoveryBatchOperation(recipientIdsToLookup: batchIds)
|
||||
batchOperation.delegate = self
|
||||
self.addDependency(batchOperation)
|
||||
}
|
||||
}
|
||||
|
@ -44,11 +45,24 @@ class ContactDiscoveryOperation: OWSOperation {
|
|||
|
||||
self.reportSuccess()
|
||||
}
|
||||
|
||||
// MARK: LegacyContactDiscoveryBatchOperationDelegate
|
||||
func contactDiscoverBatchOperation(_ contactDiscoverBatchOperation: LegacyContactDiscoveryBatchOperation, didFailWithError error: Error) {
|
||||
Logger.debug("\(logTag) in \(#function) canceling self and all dependencies.")
|
||||
|
||||
self.dependencies.forEach { $0.cancel() }
|
||||
self.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
protocol LegacyContactDiscoveryBatchOperationDelegate: class {
|
||||
func contactDiscoverBatchOperation(_ contactDiscoverBatchOperation: LegacyContactDiscoveryBatchOperation, didFailWithError error: Error)
|
||||
}
|
||||
|
||||
class LegacyContactDiscoveryBatchOperation: OWSOperation {
|
||||
|
||||
var registeredRecipientIds: Set<String>
|
||||
weak var delegate: LegacyContactDiscoveryBatchOperationDelegate?
|
||||
|
||||
private let recipientIdsToLookup: [String]
|
||||
private var networkManager: TSNetworkManager {
|
||||
|
@ -72,10 +86,17 @@ class LegacyContactDiscoveryBatchOperation: OWSOperation {
|
|||
override func run() {
|
||||
Logger.debug("\(logTag) in \(#function)")
|
||||
|
||||
guard !isCancelled else {
|
||||
Logger.info("\(logTag) in \(#function) no work to do, since we were canceled")
|
||||
self.reportCancelled()
|
||||
return
|
||||
}
|
||||
|
||||
var phoneNumbersByHashes: [String: String] = [:]
|
||||
|
||||
for recipientId in recipientIdsToLookup {
|
||||
let hash = Cryptography.truncatedSHA1Base64EncodedWithoutPadding(recipientId)
|
||||
assert(phoneNumbersByHashes[hash] == nil)
|
||||
phoneNumbersByHashes[hash] = recipientId
|
||||
}
|
||||
|
||||
|
@ -121,6 +142,11 @@ class LegacyContactDiscoveryBatchOperation: OWSOperation {
|
|||
CDSFeedbackOperation.operationQueue.addOperations([newCDSBatchOperation, cdsFeedbackOperation], waitUntilFinished: false)
|
||||
}
|
||||
|
||||
// Called at most one time.
|
||||
override func didFail(error: Error) {
|
||||
self.delegate?.contactDiscoverBatchOperation(self, didFailWithError: error)
|
||||
}
|
||||
|
||||
// MARK: Private Helpers
|
||||
|
||||
private func parse(response: Any?, phoneNumbersByHashes: [String: String]) throws -> Set<String> {
|
||||
|
|
|
@ -42,17 +42,27 @@ typedef NS_ENUM(NSInteger, OWSOperationState) {
|
|||
// Called at most one time.
|
||||
- (void)didSucceed;
|
||||
|
||||
// Called at most one time.
|
||||
- (void)didCancel;
|
||||
|
||||
// Called at most one time, once retry is no longer possible.
|
||||
- (void)didFailWithError:(NSError *)error NS_SWIFT_NAME(didFail(error:));
|
||||
|
||||
#pragma mark - Success/Error - Do Not Override
|
||||
|
||||
// Complete the operation successfully.
|
||||
// Should be called at most once per operation instance.
|
||||
// You must ensure that `run` cannot fail after calling `reportSuccess`.
|
||||
// Report that the operation completed successfully.
|
||||
//
|
||||
// Each invocation of `run` must make exactly one call to one of: `reportSuccess`, `reportCancelled`, or `reportError:`
|
||||
- (void)reportSuccess;
|
||||
|
||||
// Should be called at most once per `run`.
|
||||
// Call this when you abort before completion due to being cancelled.
|
||||
//
|
||||
// Each invocation of `run` must make exactly one call to one of: `reportSuccess`, `reportCancelled`, or `reportError:`
|
||||
- (void)reportCancelled;
|
||||
|
||||
// Report that the operation failed to complete due to an error.
|
||||
//
|
||||
// Each invocation of `run` must make exactly one call to one of: `reportSuccess`, `reportCancelled`, or `reportError:`
|
||||
// You must ensure that `run` cannot succeed after calling `reportError`, e.g. generally you'll write something like
|
||||
// this:
|
||||
//
|
||||
|
|
|
@ -81,6 +81,13 @@ NSString *const OWSOperationKeyIsFinished = @"isFinished";
|
|||
// Override in subclass if necessary
|
||||
}
|
||||
|
||||
// Called at most one time.
|
||||
- (void)didCancel
|
||||
{
|
||||
// no-op
|
||||
// Override in subclass if necessary
|
||||
}
|
||||
|
||||
// Called at most one time, once retry is no longer possible.
|
||||
- (void)didFailWithError:(NSError *)error
|
||||
{
|
||||
|
@ -113,6 +120,14 @@ NSString *const OWSOperationKeyIsFinished = @"isFinished";
|
|||
[self markAsComplete];
|
||||
}
|
||||
|
||||
// These methods are not intended to be subclassed
|
||||
- (void)reportCancelled
|
||||
{
|
||||
DDLogDebug(@"%@ cancelled.", self.logTag);
|
||||
[self didCancel];
|
||||
[self markAsComplete];
|
||||
}
|
||||
|
||||
- (void)reportError:(NSError *)error
|
||||
{
|
||||
DDLogDebug(@"%@ reportError: %@, fatal?: %d, retryable?: %d, remainingRetries: %lu",
|
||||
|
|
Loading…
Reference in New Issue