fix: improve push delivery for Android 14 and above#493
Conversation
Sample app builds 📱Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #493 +/- ##
=============================================
+ Coverage 41.98% 52.01% +10.03%
- Complexity 259 318 +59
=============================================
Files 99 105 +6
Lines 2320 2855 +535
Branches 344 380 +36
=============================================
+ Hits 974 1485 +511
- Misses 1247 1257 +10
- Partials 99 113 +14 ☔ View full report in Codecov by Sentry. |
|
Build available to test |
There was a problem hiding this comment.
ahhh need to remove these changes
|
|
This reverts commit 280de6b.
280de6b to
8623a75
Compare
|
|
|
|
| putString(KEY_DEVICE_TOKEN, token) | ||
| } | ||
|
|
||
| override fun saveSettings(value: String) = prefs.edit { |
There was a problem hiding this comment.
Does it make sense for this method to accept Settings so that the encoding/decoding is encapsulated within this store?
There was a problem hiding this comment.
Think it does make sense, i wanted to avoid strong coupling of serialization with storage, but since string format could it make it generic and prone to break, it probably wiser to make this method stricter.
| * reflected on Journeys. | ||
| */ | ||
| internal object EventNames { | ||
| object EventNames { |
There was a problem hiding this comment.
Curious as to why we moved this to core? It seems like those events are very related to Data Pipelines
There was a problem hiding this comment.
Because multiple modules are using it
| migrateTrackingEvents() | ||
|
|
||
| // save settings to storage | ||
| analytics.configuration.let { config -> |
There was a problem hiding this comment.
If this configuration object is available through analytics, what's the main reason for storing it locally? Is it for cases when the SDK hasn't been initialized yet?
There was a problem hiding this comment.
analytics is a dependency/part of data pipeline module, while push module doesn't rely on it. It just needs writeKey and endpoint that it can use to make the HTTP request.
| fun trackMetric(token: String, event: String, deliveryId: String, onComplete: ((Result<Unit>) -> Unit?)? = null) | ||
| } | ||
|
|
||
| class PushDeliveryTrackerImpl : PushDeliveryTracker { |
There was a problem hiding this comment.
Do any of these types need to be public?
There was a problem hiding this comment.
I thought about it, made them public when I was adding test for it. But I am going to revisit it.
| token: String, | ||
| event: String, | ||
| deliveryId: String, | ||
| onComplete: ((Result<Unit>) -> Unit?)? |
There was a problem hiding this comment.
Do we need a callback here? I'm not sure if the caller can do much in case of failure?
There was a problem hiding this comment.
Added it, in case we wanted to do some logging based on it or perform any operation based on its result.
| ) | ||
|
|
||
| // Track delivered metrics via event bus | ||
| eventBus.publish( |
There was a problem hiding this comment.
Does this mean that this event will be tracked twice if the app is open or not restricted by OS to run in the background?
There was a problem hiding this comment.
Yes, thats true. But i think its safer this way. Duplicate delivery is doesn't reflect on journeys etc but it safe guard from the fact that HTTP request can fail and we shouldn't just rely on it. The other way it becomes of offline queue so even if it fails, we have it in queue to be retried.
There was a problem hiding this comment.
So Journey's will handle this as a single delivery if we report it twice? My understanding is that this will count twice against the same delivery ID
There was a problem hiding this comment.
My understanding is that this will count twice against the same delivery ID
I am not 100% sure I get this? there were will be 2 requests in cdp and two might to journeys, but where is the count ?
There was a problem hiding this comment.
The points make sense. However, I think we can still skip sending metrics to EventBus since the implementation aligns with iOS and has lower chance of failure due to network issues as push can only be delivered when the network is available. Or maybe we could push to EventBus only in case of failure? 🤔
That said, I do agree this ensures delivered metrics are always tracked even if the request fails. Since CDP already skips duplicate requests, that shouldn't be a concern. So I'm okay with either approach we decide to continue with.
| migrateTrackingEvents() | ||
|
|
||
| // save settings to storage | ||
| analytics.configuration.let { config -> |
There was a problem hiding this comment.
Should we add a test for this?
There was a problem hiding this comment.
Let me try adding test for these
There was a problem hiding this comment.
Would be nice to add these tests for the EU region as well
messagingpush/api/messagingpush.api
Outdated
| public fun <init> ()V | ||
| public fun trackMetric (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V | ||
| } | ||
|
|
There was a problem hiding this comment.
Do we need those to be exposed publicly?
There was a problem hiding this comment.
I thought about it, made them public when I was adding test for it. But I am going to revisit it.
datapipelines/api/datapipelines.api
Outdated
| public fun getProfileAttributes ()Ljava/util/Map; | ||
| public fun getRegisteredDeviceToken ()Ljava/lang/String; | ||
| public fun getUserId ()Ljava/lang/String; | ||
| public final fun getWriteKey ()Ljava/lang/String; |
There was a problem hiding this comment.
I don't see this method actually in DataPipelinesModuleConfig, I might be missing something though
There was a problem hiding this comment.
Good catch, it was an unused variable added to CustomerIO class.
|
|
|
|
|
|
|
|
| internal class HttpClientImpl : HttpClient { | ||
|
|
||
| private val connectTimeoutMs = 15_000 | ||
| private val readTimeoutMs = 20_000 |
There was a problem hiding this comment.
Do we really need such high timeout values here? 🤔
There was a problem hiding this comment.
nope not really, got these from iOS HTTP client and then kept it for consistency. We can lower it if needed.
mahmoud-elmorabea
left a comment
There was a problem hiding this comment.
Looks good! 💯 Thanks for addressing the comments 😇
|
|
## [4.5.3](4.5.2...4.5.3) (2025-02-18) ### Bug Fixes * improve push delivery tracking for Android 14 and above ([#493](#493)) ([ea5c7a7](ea5c7a7))
closes: https://linear.app/customerio/issue/MBL-856/report-push-notification-metric-issues-instantly-dont-add-to-queue
changes: