Skip to content

Commit 8a7cd21

Browse files
committed
Add email fallback
1 parent f4d629c commit 8a7cd21

4 files changed

Lines changed: 73 additions & 1 deletion

File tree

pir/pir-impl/src/main/java/com/duckduckgo/pir/impl/common/PirRunStateHandler.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ interface PirRunStateHandler {
125125
val lastActionId: String,
126126
val durationMs: Long,
127127
val currentActionAttemptCount: Int,
128+
val generatedEmail: String? = null,
128129
) : PirRunState(broker)
129130

130131
data class BrokerRecordEmailConfirmationStarted(
@@ -626,11 +627,16 @@ class RealPirRunStateHandler @Inject constructor(
626627
}
627628

628629
private suspend fun handleBrokerRecordEmailConfirmationNeeded(pirRunState: BrokerRecordEmailConfirmationNeeded) {
630+
// Fall back to the generated email when the extracted profile has none. Brokers that use an
631+
// explicit generateEmail action (e.g. SpyFly) store the address on the state's generatedEmailData
632+
// rather than on extractedProfile, and the polling worker keys off this value to fetch the
633+
// confirmation link.
634+
val email = pirRunState.extractedProfile.email.ifEmpty { pirRunState.generatedEmail.orEmpty() }
629635
jobRecordUpdater.markOptOutAsWaitingForEmailConfirmation(
630636
profileQueryId = pirRunState.extractedProfile.profileQueryId,
631637
extractedProfileId = pirRunState.extractedProfile.dbId,
632638
brokerName = pirRunState.broker.name,
633-
email = pirRunState.extractedProfile.email,
639+
email = email,
634640
attemptId = pirRunState.attemptId,
635641
)
636642
pixelSender.reportStagePendingEmailConfirmation(

pir/pir-impl/src/main/java/com/duckduckgo/pir/impl/common/actions/BrokerStepCompletedEventHandler.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class BrokerStepCompletedEventHandler @Inject constructor(
7373
lastActionId = currentBrokerStep.step.actions[state.currentActionIndex].id,
7474
durationMs = currentTimeProvider.currentTimeMillis() - state.stageStatus.stageStartMs,
7575
currentActionAttemptCount = state.actionRetryCount + 1,
76+
generatedEmail = state.generatedEmailData?.emailAddress,
7677
),
7778
)
7879
} else {

pir/pir-impl/src/test/kotlin/com/duckduckgo/pir/impl/common/RealPirRunStateHandlerTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,32 @@ class RealPirRunStateHandlerTest {
595595
)
596596
}
597597

598+
@Test
599+
fun whenHandleBrokerRecordEmailConfirmationNeededAndExtractedProfileEmailEmptyThenUsesGeneratedEmail() =
600+
runTest {
601+
val state =
602+
BrokerRecordEmailConfirmationNeeded(
603+
broker = testBroker,
604+
extractedProfile = testExtractedProfile.copy(email = ""),
605+
attemptId = "c9982ded-021a-4251-9e03-2c58b130410f",
606+
lastActionId = "hello82ded-021a-4251-9e03-2c58b130410f",
607+
durationMs = testTotalTimeMillis,
608+
currentActionAttemptCount = 1,
609+
generatedEmail = "generated@duck.com",
610+
)
611+
whenever(mockRepository.getBrokerForName(testBrokerName)).thenReturn(testBroker)
612+
613+
testee.handleState(state)
614+
615+
verify(mockJobRecordUpdater).markOptOutAsWaitingForEmailConfirmation(
616+
profileQueryId = testProfileQueryId,
617+
extractedProfileId = testExtractedProfileId,
618+
brokerName = testBrokerName,
619+
email = "generated@duck.com",
620+
attemptId = "c9982ded-021a-4251-9e03-2c58b130410f",
621+
)
622+
}
623+
598624
@Test
599625
fun whenHandleBrokerRecordEmailConfirmationStartedThenUpdateEmailJobRecordAndEmitPixel() =
600626
runTest {

pir/pir-impl/src/test/kotlin/com/duckduckgo/pir/impl/common/actions/BrokerStepCompletedEventHandlerTest.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,45 @@ class BrokerStepCompletedEventHandlerTest {
204204
assertEquals("action-3", capturedState.firstValue.lastActionId)
205205
assertEquals(testCurrentTimeInMillis - testStageStartMs, capturedState.firstValue.durationMs)
206206
assertEquals(2, capturedState.firstValue.currentActionAttemptCount)
207+
assertNull(capturedState.firstValue.generatedEmail)
208+
}
209+
210+
@Test
211+
fun whenNeedsEmailConfirmationTrueAndGeneratedEmailDataPresentThenForwardsGeneratedEmail() = runTest {
212+
val optOutStep = OptOutStep(
213+
broker = testBroker,
214+
step = OptOutStepActions(
215+
stepType = "optout",
216+
actions = listOf(testAction1, testAction2, testAction3),
217+
optOutType = "form",
218+
),
219+
profileToOptOut = testExtractedProfile,
220+
)
221+
val state = State(
222+
runType = RunType.OPTOUT,
223+
brokerStepsToExecute = listOf(optOutStep),
224+
profileQuery = testProfileQuery,
225+
currentBrokerStepIndex = 0,
226+
currentActionIndex = 2,
227+
actionRetryCount = 1,
228+
attemptId = "attempt-123",
229+
brokerStepStartTime = testBrokerStartTime,
230+
generatedEmailData = testGeneratedEmailData,
231+
stageStatus = PirStageStatus(
232+
currentStage = PirStage.FILL_FORM,
233+
stageStartMs = testStageStartMs,
234+
),
235+
)
236+
val event = BrokerStepCompleted(
237+
needsEmailConfirmation = true,
238+
stepStatus = StepStatus.Success,
239+
)
240+
241+
testee.invoke(state, event)
242+
243+
val capturedState = argumentCaptor<BrokerRecordEmailConfirmationNeeded>()
244+
verify(mockPirRunStateHandler).handleState(capturedState.capture())
245+
assertEquals("generated@example.com", capturedState.firstValue.generatedEmail)
207246
}
208247

209248
@Test

0 commit comments

Comments
 (0)