Skip to content

Commit

Permalink
Add stage to failure opt out pixel (#1774)
Browse files Browse the repository at this point in the history
  • Loading branch information
jotaemepereira authored Oct 20, 2023
1 parent 0545dac commit 111fe77
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGoDBPTests/DataBrokerProtectionPixelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ final class DataBrokerProtectionPixelTests: XCTestCase {
.optOutFinish(dataBroker: "a", attemptId: UUID(), duration: 5),
.optOutSubmitSuccess(dataBroker: "a", attemptId: UUID(), duration: 5),
.optOutSuccess(dataBroker: "a", attemptId: UUID(), duration: 5),
.optOutFailure(dataBroker: "a", attemptId: UUID(), duration: 5)
.optOutFailure(dataBroker: "a", attemptId: UUID(), duration: 5, stage: "some")
]

for event in eventsToTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ extension DataBrokerOperation {

if action as? SolveCaptchaAction != nil, let captchaTransactionId = actionsHandler?.captchaTransactionId {
actionsHandler?.captchaTransactionId = nil
stageCalculator?.setStage(.captchaSolve)
if let captchaData = try? await captchaService.submitCaptchaToBeResolved(for: captchaTransactionId,
shouldRunNextStep: shouldRunNextStep) {
stageCalculator?.fireOptOutCaptchaSolve()
Expand All @@ -97,6 +98,7 @@ extension DataBrokerOperation {

if action.needsEmail {
do {
stageCalculator?.setStage(.emailGenerate)
extractedProfile?.email = try await emailService.getEmail()
stageCalculator?.fireOptOutEmailGenerate()
} catch {
Expand All @@ -112,6 +114,7 @@ extension DataBrokerOperation {
//
// https://app.asana.com/0/1203581873609357/1205476538384291/f
retriesCountOnError = 3
stageCalculator?.setStage(.captchaParse)
}

if let extractedProfile = self.extractedProfile {
Expand All @@ -123,13 +126,15 @@ extension DataBrokerOperation {

private func runEmailConfirmationAction(action: EmailConfirmationAction) async throws {
if let email = extractedProfile?.email {
stageCalculator?.setStage(.emailReceive)
let url = try await emailService.getConfirmationLink(
from: email,
numberOfRetries: 100, // Move to constant
pollingIntervalInSeconds: action.pollingTime,
shouldRunNextStep: shouldRunNextStep
)
stageCalculator?.fireOptOutEmailReceive()
stageCalculator?.setStage(.emailReceive)
try? await webViewHandler?.load(url: url)
stageCalculator?.fireOptOutEmailConfirm()
} else {
Expand Down Expand Up @@ -178,6 +183,7 @@ extension DataBrokerOperation {
func captchaInformation(captchaInfo: GetCaptchaInfoResponse) async {
do {
stageCalculator?.fireOptOutCaptchaParse()
stageCalculator?.setStage(.captchaSend)
actionsHandler?.captchaTransactionId = try await captchaService.submitCaptchaInformation(captchaInfo,
shouldRunNextStep: shouldRunNextStep)
stageCalculator?.fireOptOutCaptchaSend()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,25 @@ import PixelKit

final class DataBrokerProtectionStageDurationCalculator {

enum Stage: String {
case start
case emailGenerate = "email-generate"
case captchaParse = "captcha-parse"
case captchaSend = "captcha-send"
case captchaSolve = "captcha-solve"
case submit
case emailReceive = "email-receive"
case emailConfirm = "email-confirm"
case validate
case other
}

let handler: EventMapping<DataBrokerProtectionPixels>
let attemptId: UUID
let dataBroker: String
let startTime: Date
var lastStateTime: Date
var stage: Stage = .other

init(attemptId: UUID = UUID(),
startTime: Date = Date(),
Expand Down Expand Up @@ -56,6 +70,7 @@ final class DataBrokerProtectionStageDurationCalculator {
}

func fireOptOutStart() {
setStage(.start)
handler.fire(.optOutStart(dataBroker: dataBroker, attemptId: attemptId))
}

Expand All @@ -76,6 +91,7 @@ final class DataBrokerProtectionStageDurationCalculator {
}

func fireOptOutSubmit() {
setStage(.submit)
handler.fire(.optOutSubmit(dataBroker: dataBroker, attemptId: attemptId, duration: durationSinceLastStage()))
}

Expand All @@ -88,6 +104,7 @@ final class DataBrokerProtectionStageDurationCalculator {
}

func fireOptOutValidate() {
setStage(.validate)
handler.fire(.optOutValidate(dataBroker: dataBroker, attemptId: attemptId, duration: durationSinceLastStage()))
}

Expand All @@ -96,7 +113,14 @@ final class DataBrokerProtectionStageDurationCalculator {
}

func fireOptOutFailure() {
handler.fire(.optOutFailure(dataBroker: dataBroker, attemptId: attemptId, duration: durationSinceStartTime()))
handler.fire(.optOutFailure(dataBroker: dataBroker, attemptId: attemptId, duration: durationSinceStartTime(), stage: stage.rawValue))
}

// Helper methods to set the stage that is about to run. This help us
// identifying the stage so we can know which one was the one that failed.

func setStage(_ stage: Stage) {
self.stage = stage
}
}

Expand All @@ -106,6 +130,7 @@ public enum DataBrokerProtectionPixels: Equatable {
static let appVersionParamKey = "app_version"
static let attemptIdParamKey = "attempt_id"
static let durationParamKey = "duration"
static let stageKey = "stage"
}

case error(error: DataBrokerProtectionError, dataBroker: String)
Expand All @@ -126,7 +151,7 @@ public enum DataBrokerProtectionPixels: Equatable {
// Process Pixels
case optOutSubmitSuccess(dataBroker: String, attemptId: UUID, duration: Double)
case optOutSuccess(dataBroker: String, attemptId: UUID, duration: Double)
case optOutFailure(dataBroker: String, attemptId: UUID, duration: Double)
case optOutFailure(dataBroker: String, attemptId: UUID, duration: Double, stage: String)
}

extension DataBrokerProtectionPixels: PixelKitEvent {
Expand Down Expand Up @@ -197,8 +222,8 @@ extension DataBrokerProtectionPixels: PixelKitEvent {
return [Consts.dataBrokerParamKey: dataBroker, Consts.attemptIdParamKey: attemptId.uuidString, Consts.durationParamKey: String(duration)]
case .optOutSuccess(let dataBroker, let attemptId, let duration):
return [Consts.dataBrokerParamKey: dataBroker, Consts.attemptIdParamKey: attemptId.uuidString, Consts.durationParamKey: String(duration)]
case .optOutFailure(let dataBroker, let attemptId, let duration):
return [Consts.dataBrokerParamKey: dataBroker, Consts.attemptIdParamKey: attemptId.uuidString, Consts.durationParamKey: String(duration)]
case .optOutFailure(let dataBroker, let attemptId, let duration, let stage):
return [Consts.dataBrokerParamKey: dataBroker, Consts.attemptIdParamKey: attemptId.uuidString, Consts.durationParamKey: String(duration), Consts.stageKey: stage]
}
}
}

0 comments on commit 111fe77

Please sign in to comment.