Skip to content

Commit

Permalink
Add retry option for CCF operations (#1753)
Browse files Browse the repository at this point in the history
  • Loading branch information
jotaemepereira authored Oct 16, 2023
1 parent 8746ed5 commit 2eaeea5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ final class ActionsHandler {
self.step = step
}

func currentAction() -> Action? {
guard let lastExecutedActionIndex = self.lastExecutedActionIndex else { return nil }

if lastExecutedActionIndex < step.actions.count {
return step.actions[lastExecutedActionIndex]
} else {
return nil
}
}

func nextAction() -> Action? {
guard let lastExecutedActionIndex = self.lastExecutedActionIndex else {
// If last executed action index is nil. Means we didn't execute any action, so we return the first action.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ protocol DataBrokerOperation: CCFCommunicationDelegate {
var continuation: CheckedContinuation<ReturnValue, Error>? { get set }
var extractedProfile: ExtractedProfile? { get set }
var shouldRunNextStep: () -> Bool { get }
var retriesCountOnError: Int { get set }

func run(inputValue: InputValue,
webViewHandler: WebViewHandler?,
Expand All @@ -46,6 +47,7 @@ protocol DataBrokerOperation: CCFCommunicationDelegate {
showWebView: Bool) async throws -> ReturnValue

func executeNextStep() async
func executeCurrentAction() async
}

extension DataBrokerOperation {
Expand Down Expand Up @@ -103,6 +105,15 @@ extension DataBrokerOperation {
}
}

if action as? GetCaptchaInfoAction != nil {
// Captcha is a third-party resource that sometimes takes more time to load
// if we are not able to get the captcha information. We will try to run the action again
// instead of failing the whole thing.
//
// https://app.asana.com/0/1203581873609357/1205476538384291/f
retriesCountOnError = 3
}

if let extractedProfile = self.extractedProfile {
await webViewHandler?.execute(action: action, data: .extractedProfile(extractedProfile))
} else {
Expand Down Expand Up @@ -191,7 +202,23 @@ extension DataBrokerOperation {
}

func onError(error: DataBrokerProtectionError) async {
await webViewHandler?.finish()
failed(with: error)
if retriesCountOnError > 0 {
await executeCurrentAction()
} else {
await webViewHandler?.finish()
failed(with: error)
}
}

func executeCurrentAction() async {
let waitTimeUntilRunningTheActionAgain: TimeInterval = 3
try? await Task.sleep(nanoseconds: UInt64(waitTimeUntilRunningTheActionAgain) * 1_000_000_000)

if let currentAction = self.actionsHandler?.currentAction() {
retriesCountOnError -= 1
await runNextAction(currentAction)
} else {
await onError(error: .unknown("No current action to execute"))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class OptOutOperation: DataBrokerOperation {
var stageCalculator: DataBrokerProtectionStageDurationCalculator?
private let operationAwaitTime: TimeInterval
let shouldRunNextStep: () -> Bool
var retriesCountOnError: Int = 0

init(privacyConfig: PrivacyConfigurationManaging,
prefs: ContentScopeProperties,
Expand Down Expand Up @@ -97,6 +98,7 @@ final class OptOutOperation: DataBrokerOperation {
}

func executeNextStep() async {
retriesCountOnError = 0 // We reset the retries on error when it is successful
os_log("OPTOUT Waiting %{public}f seconds...", log: .action, operationAwaitTime)
try? await Task.sleep(nanoseconds: UInt64(operationAwaitTime) * 1_000_000_000)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ final class ScanOperation: DataBrokerOperation {
var stageCalculator: DataBrokerProtectionStageDurationCalculator?
private let operationAwaitTime: TimeInterval
let shouldRunNextStep: () -> Bool
var retriesCountOnError: Int = 0

init(privacyConfig: PrivacyConfigurationManaging,
prefs: ContentScopeProperties,
query: BrokerProfileQueryData,
emailService: EmailServiceProtocol = EmailService(),
captchaService: CaptchaServiceProtocol = CaptchaService(),
operationAwaitTime: TimeInterval = 1,
operationAwaitTime: TimeInterval = 3,
shouldRunNextStep: @escaping () -> Bool
) {
self.privacyConfig = privacyConfig
Expand Down Expand Up @@ -92,6 +93,7 @@ final class ScanOperation: DataBrokerOperation {
}

func executeNextStep() async {
retriesCountOnError = 0 // We reset the retries on error when it is successful
os_log("SCAN Waiting %{public}f seconds...", log: .action, operationAwaitTime)

try? await Task.sleep(nanoseconds: UInt64(operationAwaitTime) * 1_000_000_000)
Expand Down

0 comments on commit 2eaeea5

Please sign in to comment.