Skip to content

Commit 632fc4d

Browse files
authored
Coroutines - convert shopper insights to suspend functions (#1542)
* create session fun converstion * update function conversion * generate recs conversion plus clean up * update tests * formatting * PR comments
1 parent 227d641 commit 632fc4d

File tree

8 files changed

+247
-261
lines changed

8 files changed

+247
-261
lines changed

ShopperInsights/src/main/java/com/braintreepayments/api/shopperinsights/v2/ShopperInsightsClientV2.kt

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ import com.braintreepayments.api.shopperinsights.ShopperInsightsAnalytics.BUTTON
1515
import com.braintreepayments.api.shopperinsights.v2.internal.CreateCustomerSessionApi
1616
import com.braintreepayments.api.shopperinsights.v2.internal.UpdateCustomerSessionApi
1717
import com.braintreepayments.api.shopperinsights.v2.internal.GenerateCustomerRecommendationsApi
18+
import com.braintreepayments.api.shopperinsights.v2.internal.GenerateCustomerRecommendationsApi.GenerateCustomerRecommendationsResult
19+
import kotlinx.coroutines.CoroutineDispatcher
20+
import kotlinx.coroutines.CoroutineScope
21+
import kotlinx.coroutines.Dispatchers
22+
import kotlinx.coroutines.launch
1823

1924
/**
2025
* Use [ShopperInsightsClientV2] to optimize your checkout experience by prioritizing the customer’s preferred payment
@@ -36,7 +41,9 @@ class ShopperInsightsClientV2 internal constructor(
3641
private val generateCustomerRecommendationsApi: GenerateCustomerRecommendationsApi =
3742
GenerateCustomerRecommendationsApi(braintreeClient),
3843
private val deviceInspector: DeviceInspector = DeviceInspectorProvider().deviceInspector,
39-
lazyAnalyticsClient: Lazy<AnalyticsClient> = AnalyticsClient.lazyInstance
44+
lazyAnalyticsClient: Lazy<AnalyticsClient> = AnalyticsClient.lazyInstance,
45+
private val mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
46+
private val coroutineScope: CoroutineScope = CoroutineScope(mainDispatcher)
4047
) {
4148

4249
/**
@@ -64,18 +71,27 @@ class ShopperInsightsClientV2 internal constructor(
6471
customerSessionRequest: CustomerSessionRequest,
6572
customerSessionCallback: (customerSessionResult: CustomerSessionResult) -> Unit
6673
) {
74+
coroutineScope.launch {
75+
val result = createCustomerSession(customerSessionRequest)
76+
customerSessionCallback(result)
77+
}
78+
}
79+
80+
private suspend fun createCustomerSession(
81+
customerSessionRequest: CustomerSessionRequest
82+
): CustomerSessionResult {
6783
analyticsClient.sendEvent(ShopperInsightsAnalytics.CREATE_CUSTOMER_SESSION_STARTED)
68-
createCustomerSessionApi.execute(customerSessionRequest) { createCustomerSessionResult ->
69-
when (createCustomerSessionResult) {
70-
is CreateCustomerSessionApi.CreateCustomerSessionResult.Success -> {
71-
analyticsClient.sendEvent(ShopperInsightsAnalytics.CREATE_CUSTOMER_SESSION_SUCCEEDED)
72-
customerSessionCallback(CustomerSessionResult.Success(createCustomerSessionResult.sessionId))
73-
}
74-
75-
is CreateCustomerSessionApi.CreateCustomerSessionResult.Error -> {
76-
analyticsClient.sendEvent(ShopperInsightsAnalytics.CREATE_CUSTOMER_SESSION_FAILED)
77-
customerSessionCallback(CustomerSessionResult.Failure(createCustomerSessionResult.error))
78-
}
84+
return when (
85+
val createCustomerSessionResult = createCustomerSessionApi.execute(customerSessionRequest)
86+
) {
87+
is CreateCustomerSessionApi.CreateCustomerSessionResult.Success -> {
88+
analyticsClient.sendEvent(ShopperInsightsAnalytics.CREATE_CUSTOMER_SESSION_SUCCEEDED)
89+
CustomerSessionResult.Success(createCustomerSessionResult.sessionId)
90+
}
91+
92+
is CreateCustomerSessionApi.CreateCustomerSessionResult.Error -> {
93+
analyticsClient.sendEvent(ShopperInsightsAnalytics.CREATE_CUSTOMER_SESSION_FAILED)
94+
CustomerSessionResult.Failure(createCustomerSessionResult.error)
7995
}
8096
}
8197
}
@@ -94,18 +110,28 @@ class ShopperInsightsClientV2 internal constructor(
94110
sessionId: String,
95111
customerSessionCallback: (customerSessionResult: CustomerSessionResult) -> Unit
96112
) {
113+
coroutineScope.launch {
114+
val result = updateCustomerSession(customerSessionRequest, sessionId)
115+
customerSessionCallback(result)
116+
}
117+
}
118+
119+
private suspend fun updateCustomerSession(
120+
customerSessionRequest: CustomerSessionRequest,
121+
sessionId: String
122+
): CustomerSessionResult {
97123
analyticsClient.sendEvent(ShopperInsightsAnalytics.UPDATE_CUSTOMER_SESSION_STARTED)
98-
updateCustomerSessionApi.execute(customerSessionRequest, sessionId) { result ->
99-
when (result) {
100-
is UpdateCustomerSessionApi.UpdateCustomerSessionResult.Success -> {
101-
analyticsClient.sendEvent(ShopperInsightsAnalytics.UPDATE_CUSTOMER_SESSION_SUCCEEDED)
102-
customerSessionCallback(CustomerSessionResult.Success(result.sessionId))
103-
}
104-
105-
is UpdateCustomerSessionApi.UpdateCustomerSessionResult.Error -> {
106-
analyticsClient.sendEvent(ShopperInsightsAnalytics.UPDATE_CUSTOMER_SESSION_FAILED)
107-
customerSessionCallback(CustomerSessionResult.Failure(result.error))
108-
}
124+
return when (
125+
val updateCustomerSessionResult = updateCustomerSessionApi.execute(customerSessionRequest, sessionId)
126+
) {
127+
is UpdateCustomerSessionApi.UpdateCustomerSessionResult.Success -> {
128+
analyticsClient.sendEvent(ShopperInsightsAnalytics.UPDATE_CUSTOMER_SESSION_SUCCEEDED)
129+
CustomerSessionResult.Success(updateCustomerSessionResult.sessionId)
130+
}
131+
132+
is UpdateCustomerSessionApi.UpdateCustomerSessionResult.Error -> {
133+
analyticsClient.sendEvent(ShopperInsightsAnalytics.UPDATE_CUSTOMER_SESSION_FAILED)
134+
CustomerSessionResult.Failure(updateCustomerSessionResult.error)
109135
}
110136
}
111137
}
@@ -125,28 +151,30 @@ class ShopperInsightsClientV2 internal constructor(
125151
sessionId: String? = null,
126152
customerRecommendationsCallback: (customerRecommendationsResult: CustomerRecommendationsResult) -> Unit
127153
) {
154+
coroutineScope.launch {
155+
val result = generateCustomerRecommendations(customerSessionRequest, sessionId)
156+
customerRecommendationsCallback(result)
157+
}
158+
}
159+
160+
private suspend fun generateCustomerRecommendations(
161+
customerSessionRequest: CustomerSessionRequest? = null,
162+
sessionId: String? = null,
163+
): CustomerRecommendationsResult {
128164
analyticsClient.sendEvent(ShopperInsightsAnalytics.GET_CUSTOMER_RECOMMENDATIONS_STARTED)
129-
generateCustomerRecommendationsApi.execute(customerSessionRequest, sessionId) {
130-
generateCustomerRecommendationsResult ->
131-
when (generateCustomerRecommendationsResult) {
132-
is GenerateCustomerRecommendationsApi.GenerateCustomerRecommendationsResult.Success -> {
133-
analyticsClient.sendEvent(ShopperInsightsAnalytics.GET_CUSTOMER_RECOMMENDATIONS_SUCCEEDED)
134-
customerRecommendationsCallback(
135-
CustomerRecommendationsResult.Success(
136-
generateCustomerRecommendationsResult.customerRecommendations
137-
)
138-
)
139-
}
140-
141-
is GenerateCustomerRecommendationsApi.GenerateCustomerRecommendationsResult.Error -> {
142-
analyticsClient.sendEvent(ShopperInsightsAnalytics.GET_CUSTOMER_RECOMMENDATIONS_FAILED)
143-
customerRecommendationsCallback(
144-
CustomerRecommendationsResult.Failure(
145-
generateCustomerRecommendationsResult.error
146-
)
147-
)
148-
}
149-
}
165+
return when (
166+
val generateCustomerRecommendationsResult =
167+
generateCustomerRecommendationsApi.execute(customerSessionRequest, sessionId)
168+
) {
169+
is GenerateCustomerRecommendationsResult.Success -> {
170+
analyticsClient.sendEvent(ShopperInsightsAnalytics.GET_CUSTOMER_RECOMMENDATIONS_SUCCEEDED)
171+
CustomerRecommendationsResult.Success(generateCustomerRecommendationsResult.customerRecommendations)
172+
}
173+
174+
is GenerateCustomerRecommendationsResult.Error -> {
175+
analyticsClient.sendEvent(ShopperInsightsAnalytics.GET_CUSTOMER_RECOMMENDATIONS_FAILED)
176+
CustomerRecommendationsResult.Failure(generateCustomerRecommendationsResult.error)
177+
}
150178
}
151179
}
152180

ShopperInsights/src/main/java/com/braintreepayments/api/shopperinsights/v2/internal/CreateCustomerSessionApi.kt

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,49 @@ package com.braintreepayments.api.shopperinsights.v2.internal
33
import com.braintreepayments.api.core.BraintreeClient
44
import com.braintreepayments.api.core.ExperimentalBetaApi
55
import com.braintreepayments.api.shopperinsights.v2.CustomerSessionRequest
6-
import kotlinx.coroutines.CoroutineDispatcher
7-
import kotlinx.coroutines.CoroutineScope
8-
import kotlinx.coroutines.Dispatchers
9-
import kotlinx.coroutines.launch
106
import org.json.JSONException
117
import org.json.JSONObject
12-
import java.io.IOException
138

149
/**
1510
* API to create a new customer session using the `CreateCustomerSession` GraphQL mutation.
1611
*/
1712
@ExperimentalBetaApi
13+
@Suppress("TooGenericExceptionCaught")
1814
internal class CreateCustomerSessionApi(
1915
private val braintreeClient: BraintreeClient,
2016
private val customerSessionRequestBuilder: CustomerSessionRequestBuilder = CustomerSessionRequestBuilder(),
21-
private val responseParser: ShopperInsightsResponseParser = ShopperInsightsResponseParser(),
22-
private val mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
23-
private val coroutineScope: CoroutineScope = CoroutineScope(mainDispatcher)
17+
private val responseParser: ShopperInsightsResponseParser = ShopperInsightsResponseParser()
2418
) {
2519

2620
sealed class CreateCustomerSessionResult {
2721
data class Success(val sessionId: String) : CreateCustomerSessionResult()
2822
data class Error(val error: Exception) : CreateCustomerSessionResult()
2923
}
3024

31-
fun execute(
32-
customerSessionRequest: CustomerSessionRequest,
33-
callback: (CreateCustomerSessionResult) -> Unit
34-
) {
35-
try {
25+
suspend fun execute(customerSessionRequest: CustomerSessionRequest): CreateCustomerSessionResult {
26+
return try {
3627
val params = JSONObject()
3728
params.put(
3829
QUERY, """
39-
mutation CreateCustomerSession(${'$'}input: CreateCustomerSessionInput!) {
40-
createCustomerSession(input: ${'$'}input) {
41-
sessionId
42-
}
30+
mutation CreateCustomerSession(${'$'}input: CreateCustomerSessionInput!) {
31+
createCustomerSession(input: ${'$'}input) {
32+
sessionId
4333
}
44-
""".trimIndent()
34+
}
35+
""".trimIndent()
4536
)
4637

4738
params.put(VARIABLES, assembleVariables(customerSessionRequest))
4839

49-
coroutineScope.launch {
50-
try {
51-
val responseBody = braintreeClient.sendGraphQLPOST(params)
52-
val sessionId =
53-
responseParser.parseSessionId(responseBody, CREATE_CUSTOMER_SESSION)
54-
callback(
55-
CreateCustomerSessionResult.Success(sessionId)
56-
)
57-
} catch (e: IOException) {
58-
callback(CreateCustomerSessionResult.Error(e))
59-
} catch (e: JSONException) {
60-
callback(CreateCustomerSessionResult.Error(e))
61-
}
40+
try {
41+
val responseBody = braintreeClient.sendGraphQLPOST(params)
42+
val sessionId = responseParser.parseSessionId(responseBody, CREATE_CUSTOMER_SESSION)
43+
CreateCustomerSessionResult.Success(sessionId)
44+
} catch (e: Exception) {
45+
CreateCustomerSessionResult.Error(e)
6246
}
6347
} catch (e: JSONException) {
64-
callback(CreateCustomerSessionResult.Error(e))
48+
CreateCustomerSessionResult.Error(e)
6549
}
6650
}
6751

ShopperInsights/src/main/java/com/braintreepayments/api/shopperinsights/v2/internal/GenerateCustomerRecommendationsApi.kt

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,17 @@ import com.braintreepayments.api.core.ExperimentalBetaApi
55
import com.braintreepayments.api.shopperinsights.v2.CustomerRecommendations
66
import com.braintreepayments.api.shopperinsights.v2.CustomerSessionRequest
77
import com.braintreepayments.api.shopperinsights.v2.PaymentOptions
8-
import kotlinx.coroutines.CoroutineDispatcher
9-
import kotlinx.coroutines.CoroutineScope
10-
import kotlinx.coroutines.Dispatchers
11-
import kotlinx.coroutines.launch
128
import org.json.JSONException
139
import org.json.JSONObject
14-
import java.io.IOException
1510

1611
/**
1712
* API to return customer recommendations using the `GenerateCustomerRecommendations` GraphQL mutation.
1813
*/
1914
@ExperimentalBetaApi
15+
@Suppress("TooGenericExceptionCaught")
2016
internal class GenerateCustomerRecommendationsApi(
2117
private val braintreeClient: BraintreeClient,
22-
private val customerSessionRequestBuilder: CustomerSessionRequestBuilder = CustomerSessionRequestBuilder(),
23-
private val mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
24-
private val coroutineScope: CoroutineScope = CoroutineScope(mainDispatcher)
18+
private val customerSessionRequestBuilder: CustomerSessionRequestBuilder = CustomerSessionRequestBuilder()
2519
) {
2620

2721
sealed class GenerateCustomerRecommendationsResult {
@@ -32,12 +26,11 @@ internal class GenerateCustomerRecommendationsApi(
3226
data class Error(val error: Exception) : GenerateCustomerRecommendationsResult()
3327
}
3428

35-
fun execute(
29+
suspend fun execute(
3630
customerSessionRequest: CustomerSessionRequest?,
37-
sessionId: String?,
38-
callback: (GenerateCustomerRecommendationsResult) -> Unit
39-
) {
40-
try {
31+
sessionId: String?
32+
): GenerateCustomerRecommendationsResult {
33+
return try {
4134
val params = JSONObject()
4235
params.put(
4336
QUERY, """
@@ -55,19 +48,16 @@ internal class GenerateCustomerRecommendationsApi(
5548
)
5649

5750
params.put(VARIABLES, assembleVariables(sessionId, customerSessionRequest))
58-
coroutineScope.launch {
59-
try {
60-
val responseBody = braintreeClient.sendGraphQLPOST(params)
61-
val recommendationsResult = parseRecommendationsResponse(responseBody)
62-
callback(GenerateCustomerRecommendationsResult.Success(recommendationsResult))
63-
} catch (e: IOException) {
64-
callback(GenerateCustomerRecommendationsResult.Error(e))
65-
} catch (e: JSONException) {
66-
callback(GenerateCustomerRecommendationsResult.Error(e))
67-
}
51+
52+
try {
53+
val responseBody = braintreeClient.sendGraphQLPOST(params)
54+
val recommendationsResult = parseRecommendationsResponse(responseBody)
55+
GenerateCustomerRecommendationsResult.Success(recommendationsResult)
56+
} catch (e: Exception) {
57+
GenerateCustomerRecommendationsResult.Error(e)
6858
}
6959
} catch (e: JSONException) {
70-
callback(GenerateCustomerRecommendationsResult.Error(e))
60+
GenerateCustomerRecommendationsResult.Error(e)
7161
}
7262
}
7363

ShopperInsights/src/main/java/com/braintreepayments/api/shopperinsights/v2/internal/UpdateCustomerSessionApi.kt

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,30 @@ package com.braintreepayments.api.shopperinsights.v2.internal
33
import com.braintreepayments.api.core.BraintreeClient
44
import com.braintreepayments.api.core.ExperimentalBetaApi
55
import com.braintreepayments.api.shopperinsights.v2.CustomerSessionRequest
6-
import kotlinx.coroutines.CoroutineDispatcher
7-
import kotlinx.coroutines.CoroutineScope
8-
import kotlinx.coroutines.Dispatchers
9-
import kotlinx.coroutines.launch
106
import org.json.JSONException
117
import org.json.JSONObject
12-
import java.io.IOException
138

149
/**
1510
* API to update an existing customer session using the `UpdateCustomerSession` GraphQL mutation.
1611
*/
1712
@ExperimentalBetaApi
13+
@Suppress("TooGenericExceptionCaught")
1814
internal class UpdateCustomerSessionApi(
1915
private val braintreeClient: BraintreeClient,
2016
private val customerSessionRequestBuilder: CustomerSessionRequestBuilder = CustomerSessionRequestBuilder(),
21-
private val responseParser: ShopperInsightsResponseParser = ShopperInsightsResponseParser(),
22-
private val mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
23-
private val coroutineScope: CoroutineScope = CoroutineScope(mainDispatcher)
17+
private val responseParser: ShopperInsightsResponseParser = ShopperInsightsResponseParser()
2418
) {
2519

2620
sealed class UpdateCustomerSessionResult {
2721
data class Success(val sessionId: String) : UpdateCustomerSessionResult()
2822
data class Error(val error: Exception) : UpdateCustomerSessionResult()
2923
}
3024

31-
fun execute(
25+
suspend fun execute(
3226
customerSessionRequest: CustomerSessionRequest,
3327
sessionId: String,
34-
callback: (UpdateCustomerSessionResult) -> Unit
35-
) {
36-
try {
28+
): UpdateCustomerSessionResult {
29+
return try {
3730
val params = JSONObject()
3831
params.put(
3932
QUERY, """
@@ -47,21 +40,15 @@ internal class UpdateCustomerSessionApi(
4740

4841
params.put(VARIABLES, assembleVariables(sessionId, customerSessionRequest))
4942

50-
coroutineScope.launch {
5143
try {
5244
val responseBody = braintreeClient.sendGraphQLPOST(params)
5345
val sessionId = responseParser.parseSessionId(responseBody, UPDATE_CUSTOMER_SESSION)
54-
callback(
55-
UpdateCustomerSessionResult.Success(sessionId)
56-
)
57-
} catch (e: IOException) {
58-
callback(UpdateCustomerSessionResult.Error(e))
59-
} catch (e: JSONException) {
60-
callback(UpdateCustomerSessionResult.Error(e))
46+
UpdateCustomerSessionResult.Success(sessionId)
47+
} catch (e: Exception) {
48+
UpdateCustomerSessionResult.Error(e)
6149
}
62-
}
6350
} catch (e: JSONException) {
64-
callback(UpdateCustomerSessionResult.Error(e))
51+
UpdateCustomerSessionResult.Error(e)
6552
}
6653
}
6754

0 commit comments

Comments
 (0)