Skip to content

Commit a21da76

Browse files
authored
Fix settings not propogate to plugins when offline (#269)
* update gradle * propagate cached settings object in network failure * fetch settings when app is brought to foreground
1 parent c2ac4ea commit a21da76

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

android/src/main/java/com/segment/analytics/kotlin/android/AndroidAnalytics.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ package com.segment.analytics.kotlin.android
33
import android.content.Context
44
import android.content.Intent
55
import android.util.Log
6+
import androidx.lifecycle.DefaultLifecycleObserver
7+
import androidx.lifecycle.LifecycleOwner
8+
import androidx.lifecycle.ProcessLifecycleOwner
69
import com.segment.analytics.kotlin.android.plugins.AndroidContextPlugin
710
import com.segment.analytics.kotlin.android.plugins.AndroidLifecyclePlugin
811
import com.segment.analytics.kotlin.android.utilities.DeepLinkUtils
912
import com.segment.analytics.kotlin.core.Analytics
1013
import com.segment.analytics.kotlin.core.Configuration
14+
import com.segment.analytics.kotlin.core.checkSettings
1115
import com.segment.analytics.kotlin.core.platform.plugins.logger.*
16+
import kotlinx.coroutines.Dispatchers
17+
import kotlinx.coroutines.launch
1218

1319
// A set of functions tailored to the Android implementation of analytics
1420

@@ -67,6 +73,25 @@ public fun Analytics(
6773
private fun Analytics.startup() {
6874
add(AndroidContextPlugin())
6975
add(AndroidLifecyclePlugin())
76+
registerLifecycle()
77+
}
78+
79+
private fun Analytics.registerLifecycle() {
80+
analyticsScope.launch(Dispatchers.Main) {
81+
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
82+
var lastCheckSettings = java.lang.System.currentTimeMillis()
83+
val CHECK_SETTINGS_INTERVAL = 10 * 1000L
84+
85+
override fun onStart(owner: LifecycleOwner) {
86+
analyticsScope.launch(analyticsDispatcher) {
87+
if (java.lang.System.currentTimeMillis() - lastCheckSettings > CHECK_SETTINGS_INTERVAL) {
88+
checkSettings()
89+
lastCheckSettings = java.lang.System.currentTimeMillis()
90+
}
91+
}
92+
}
93+
})
94+
}
7095
}
7196

7297
/**

core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,13 @@ suspend fun Analytics.checkSettings() {
9696
settingsObj?.let {
9797
log("Dispatching update settings on ${Thread.currentThread().name}")
9898
store.dispatch(System.UpdateSettingsAction(settingsObj), System::class)
99-
update(settingsObj)
99+
}
100+
101+
store.currentState(System::class)?.let { system ->
102+
system.settings?.let { settings ->
103+
log("Propagating settings on ${Thread.currentThread().name}")
104+
update(settings)
105+
}
100106
}
101107

102108
// we're good to go back to a running state.

core/src/test/kotlin/com/segment/analytics/kotlin/core/SettingsTests.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.segment.analytics.kotlin.core.platform.Plugin
55
import com.segment.analytics.kotlin.core.utils.StubPlugin
66
import com.segment.analytics.kotlin.core.utils.mockHTTPClient
77
import com.segment.analytics.kotlin.core.utils.testAnalytics
8+
import io.mockk.every
89
import io.mockk.spyk
910
import io.mockk.verify
1011
import kotlinx.coroutines.test.TestScope
@@ -75,6 +76,34 @@ class SettingsTests {
7576
}
7677

7778
@Test
79+
fun `cached settings propagates to plugins when network error`() = runTest {
80+
every { anyConstructed<HTTPClient>().settings("cdn-settings.segment.com/v1") } throws Exception()
81+
val mockPlugin = spyk(StubPlugin())
82+
83+
val settings = Settings(
84+
integrations = buildJsonObject {
85+
put(
86+
"cachedSettings",
87+
buildJsonObject {
88+
put(
89+
"apiKey",
90+
"1vNgUqwJeCHmqgI9S1sOm9UHCyfYqbaQ"
91+
)
92+
})
93+
},
94+
plan = emptyJsonObject,
95+
edgeFunction = emptyJsonObject,
96+
middlewareSettings = emptyJsonObject
97+
)
98+
analytics.store.dispatch(System.UpdateSettingsAction(settings), System::class)
99+
analytics.add(mockPlugin)
100+
verify {
101+
mockPlugin.update(settings, Plugin.UpdateType.Initial)
102+
}
103+
}
104+
105+
// Disabled because now we always propagate settings regardless network status
106+
@Test @Disabled
78107
fun `plugin added before settings is available updates plugin correctly`() = runTest {
79108
// forces settings to fail
80109
mockHTTPClient("")

gradle/codecov.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ task codeCoverageReport(type: JacocoReport) {
2929
executionData.setFrom(execData)
3030

3131
reports {
32-
xml.enabled true
33-
xml.destination file("${buildDir}/reports/jacoco/report.xml")
34-
html.enabled true
35-
csv.enabled false
32+
xml.required = true
33+
xml.outputLocation = file("${buildDir}/reports/jacoco/report.xml")
34+
html.required = true
35+
csv.required = false
3636
}
3737
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Fri Jan 22 15:05:55 PST 2021
1+
#Tue Jun 24 14:05:08 CDT 2025
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
4+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
45
zipStoreBase=GRADLE_USER_HOME
56
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

0 commit comments

Comments
 (0)