Skip to content

Commit 443b8bf

Browse files
committed
Introduce background and blocking dispatchers for Firebase alignment.
1 parent 8c12472 commit 443b8bf

File tree

12 files changed

+116
-22
lines changed

12 files changed

+116
-22
lines changed

firebase-sessions/firebase-sessions.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ dependencies {
5050
implementation("com.google.firebase:firebase-encoders:17.0.0")
5151
implementation("com.google.firebase:firebase-installations-interop:17.1.0")
5252
implementation(libs.androidx.annotation)
53+
testImplementation(project(mapOf("path" to ":integ-testing")))
5354

5455
runtimeOnly("com.google.firebase:firebase-installations:17.1.3")
5556
runtimeOnly(project(":firebase-datatransport"))

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/FirebaseSessions.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,18 @@ internal constructor(
3333
private val firebaseApp: FirebaseApp,
3434
firebaseInstallations: FirebaseInstallationsApi,
3535
backgroundDispatcher: CoroutineDispatcher,
36+
blockingDispatcher: CoroutineDispatcher,
3637
transportFactoryProvider: Provider<TransportFactory>,
3738
) {
3839
private val applicationInfo = SessionEvents.getApplicationInfo(firebaseApp)
3940
private val sessionSettings =
40-
SessionsSettings(firebaseApp.applicationContext, firebaseInstallations, applicationInfo)
41+
SessionsSettings(
42+
firebaseApp.applicationContext,
43+
blockingDispatcher,
44+
backgroundDispatcher,
45+
firebaseInstallations,
46+
applicationInfo
47+
)
4148
private val sessionGenerator = SessionGenerator(collectEvents = shouldCollectEvents())
4249
private val eventGDTLogger = EventGDTLogger(transportFactoryProvider)
4350
private val sessionCoordinator =

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/FirebaseSessionsRegistrar.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import androidx.annotation.Keep
1818
import com.google.android.datatransport.TransportFactory
1919
import com.google.firebase.FirebaseApp
2020
import com.google.firebase.annotations.concurrent.Background
21+
import com.google.firebase.annotations.concurrent.Blocking
2122
import com.google.firebase.components.*
2223
import com.google.firebase.components.Qualified.qualified
2324
import com.google.firebase.components.Qualified.unqualified
@@ -45,6 +46,7 @@ internal class FirebaseSessionsRegistrar : ComponentRegistrar {
4546
.add(Dependency.required(firebaseApp))
4647
.add(Dependency.required(firebaseInstallationsApi))
4748
.add(Dependency.required(backgroundDispatcher))
49+
.add(Dependency.required(blockingDispatcher))
4850
.add(Dependency.requiredProvider(transportFactory))
4951
.factory { container ->
5052
// Make sure FirebaseSessionsEarly has started up
@@ -53,6 +55,7 @@ internal class FirebaseSessionsRegistrar : ComponentRegistrar {
5355
container.get(firebaseApp),
5456
container.get(firebaseInstallationsApi),
5557
container.get(backgroundDispatcher),
58+
container.get(blockingDispatcher),
5659
container.getProvider(transportFactory),
5760
)
5861
}
@@ -69,6 +72,8 @@ internal class FirebaseSessionsRegistrar : ComponentRegistrar {
6972
private val firebaseInstallationsApi = unqualified(FirebaseInstallationsApi::class.java)
7073
private val backgroundDispatcher =
7174
qualified(Background::class.java, CoroutineDispatcher::class.java)
75+
private val blockingDispatcher =
76+
qualified(Blocking::class.java, CoroutineDispatcher::class.java)
7277
private val transportFactory = unqualified(TransportFactory::class.java)
7378
}
7479
}

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/settings/RemoteSettings.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ import androidx.datastore.preferences.preferencesDataStore
2222
import com.google.firebase.installations.FirebaseInstallationsApi
2323
import com.google.firebase.sessions.ApplicationInfo
2424
import java.util.concurrent.atomic.AtomicBoolean
25+
import kotlin.coroutines.CoroutineContext
2526
import kotlin.time.Duration
2627
import kotlin.time.Duration.Companion.seconds
28+
import kotlinx.coroutines.CoroutineScope
2729
import kotlinx.coroutines.Dispatchers
2830
import kotlinx.coroutines.launch
2931
import kotlinx.coroutines.runBlocking
@@ -33,6 +35,8 @@ import org.json.JSONObject
3335

3436
internal class RemoteSettings(
3537
val context: Context,
38+
val blockingDispatcher: CoroutineContext,
39+
val backgroundDispatcher: CoroutineContext,
3640
val firebaseInstallationsApi: FirebaseInstallationsApi,
3741
val appInfo: ApplicationInfo,
3842
private val configsFetcher: CrashlyticsSettingsFetcher = RemoteSettingsFetcher(appInfo),
@@ -62,15 +66,17 @@ internal class RemoteSettings(
6266
}
6367

6468
override fun updateSettings() {
65-
runBlocking { launch(Dispatchers.Default) { fetchConfigs() } }
69+
// TODO: Move to blocking coroutine dispatcher.
70+
runBlocking(Dispatchers.Default) { launch { fetchConfigs() } }
6671
}
6772

6873
override fun isSettingsStale(): Boolean {
6974
return settingsCache.hasCacheExpired()
7075
}
7176

7277
internal fun clearCachedSettings() {
73-
runBlocking { launch(Dispatchers.Default) { settingsCache.removeConfigs() } }
78+
val scope = CoroutineScope(backgroundDispatcher)
79+
scope.launch { settingsCache.removeConfigs() }
7480
}
7581

7682
suspend private fun fetchConfigs() {
@@ -134,6 +140,7 @@ internal class RemoteSettings(
134140
}
135141
}
136142

143+
val scope = CoroutineScope(backgroundDispatcher)
137144
sessionsEnabled?.let { settingsCache.updateSettingsEnabled(sessionsEnabled) }
138145

139146
sessionTimeoutSeconds?.let {

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/settings/SessionsSettings.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.google.firebase.sessions.settings
1919
import android.content.Context
2020
import com.google.firebase.installations.FirebaseInstallationsApi
2121
import com.google.firebase.sessions.ApplicationInfo
22+
import kotlin.coroutines.CoroutineContext
2223
import kotlin.time.Duration
2324
import kotlin.time.Duration.Companion.minutes
2425

@@ -29,11 +30,19 @@ import kotlin.time.Duration.Companion.minutes
2930
*/
3031
internal class SessionsSettings(
3132
val context: Context,
33+
val blockingDispatcher: CoroutineContext,
34+
val backgroundDispatcher: CoroutineContext,
3235
val firebaseInstallationsApi: FirebaseInstallationsApi,
3336
val appInfo: ApplicationInfo,
3437
private val localOverrideSettings: LocalOverrideSettings = LocalOverrideSettings(context),
3538
private val remoteSettings: RemoteSettings =
36-
RemoteSettings(context, firebaseInstallationsApi, appInfo)
39+
RemoteSettings(
40+
context,
41+
blockingDispatcher,
42+
backgroundDispatcher,
43+
firebaseInstallationsApi,
44+
appInfo
45+
)
3746
) {
3847
// Order of preference for all the configs below:
3948
// 1. Honor local overrides

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/EventGDTLoggerTest.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ import com.google.android.datatransport.Event
2121
import com.google.android.datatransport.TransportFactory
2222
import com.google.common.truth.Truth.assertThat
2323
import com.google.firebase.FirebaseApp
24+
import com.google.firebase.concurrent.TestOnlyExecutors
2425
import com.google.firebase.sessions.settings.SessionsSettings
2526
import com.google.firebase.sessions.testing.FakeFirebaseApp
2627
import com.google.firebase.sessions.testing.FakeFirebaseInstallations
2728
import com.google.firebase.sessions.testing.FakeProvider
2829
import com.google.firebase.sessions.testing.FakeTimeProvider
2930
import com.google.firebase.sessions.testing.FakeTransportFactory
3031
import com.google.firebase.sessions.testing.TestSessionEventData
32+
import kotlinx.coroutines.asCoroutineDispatcher
33+
import kotlinx.coroutines.test.runTest
3134
import org.junit.After
3235
import org.junit.Test
3336
import org.junit.runner.RunWith
@@ -37,7 +40,7 @@ import org.robolectric.RobolectricTestRunner
3740
class EventGDTLoggerTest {
3841

3942
@Test
40-
fun event_logsToGoogleDataTransport() {
43+
fun event_logsToGoogleDataTransport() = runTest {
4144
val fakeFirebaseApp = FakeFirebaseApp()
4245
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
4346
val sessionEvent =
@@ -46,6 +49,8 @@ class EventGDTLoggerTest {
4649
TestSessionEventData.TEST_SESSION_DETAILS,
4750
SessionsSettings(
4851
fakeFirebaseApp.firebaseApp.applicationContext,
52+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
53+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
4954
firebaseInstallations,
5055
SessionEvents.getApplicationInfo(fakeFirebaseApp.firebaseApp)
5156
),

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/RemoteSettingsTest.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@ package com.google.firebase.sessions
1919
import androidx.test.ext.junit.runners.AndroidJUnit4
2020
import com.google.common.truth.Truth.assertThat
2121
import com.google.firebase.FirebaseApp
22+
import com.google.firebase.concurrent.TestOnlyExecutors
2223
import com.google.firebase.sessions.settings.RemoteSettings
2324
import com.google.firebase.sessions.testing.FakeFirebaseApp
2425
import com.google.firebase.sessions.testing.FakeFirebaseInstallations
2526
import com.google.firebase.sessions.testing.FakeRemoteConfigFetcher
2627
import kotlin.time.Duration.Companion.minutes
28+
import kotlinx.coroutines.asCoroutineDispatcher
29+
import kotlinx.coroutines.test.runTest
2730
import org.json.JSONObject
2831
import org.junit.After
2932
import org.junit.Test
@@ -33,7 +36,7 @@ import org.junit.runner.RunWith
3336
class RemoteSettingsTest {
3437

3538
@Test
36-
fun RemoteSettings_successfulFetchCachesValues() {
39+
fun RemoteSettings_successfulFetchCachesValues() = runTest {
3740
val firebaseApp = FakeFirebaseApp().firebaseApp
3841
val context = firebaseApp.applicationContext
3942
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -42,6 +45,8 @@ class RemoteSettingsTest {
4245
val remoteSettings =
4346
RemoteSettings(
4447
context,
48+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
49+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
4550
firebaseInstallations,
4651
SessionEvents.getApplicationInfo(firebaseApp),
4752
fakeFetcher,
@@ -62,7 +67,7 @@ class RemoteSettingsTest {
6267
}
6368

6469
@Test
65-
fun RemoteSettings_successfulFetchWithLessConfigsCachesOnlyReceivedValues() {
70+
fun RemoteSettings_successfulFetchWithLessConfigsCachesOnlyReceivedValues() = runTest {
6671
val firebaseApp = FakeFirebaseApp().firebaseApp
6772
val context = firebaseApp.applicationContext
6873
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -71,6 +76,8 @@ class RemoteSettingsTest {
7176
val remoteSettings =
7277
RemoteSettings(
7378
context,
79+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
80+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
7481
firebaseInstallations,
7582
SessionEvents.getApplicationInfo(firebaseApp),
7683
fakeFetcher,
@@ -93,15 +100,20 @@ class RemoteSettingsTest {
93100
}
94101

95102
@Test
96-
fun RemoteSettings_successfulRefetchUpdatesCache() {
103+
fun RemoteSettings_successfulRefetchUpdatesCache() = runTest {
97104
val firebaseApp = FakeFirebaseApp().firebaseApp
98105
val context = firebaseApp.applicationContext
99106
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
100107
val fakeFetcher = FakeRemoteConfigFetcher()
101108

109+
val blockingDispatcher = TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext
110+
val backgroundDispatcher =
111+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext
102112
val remoteSettings =
103113
RemoteSettings(
104114
context,
115+
blockingDispatcher,
116+
backgroundDispatcher,
105117
firebaseInstallations,
106118
SessionEvents.getApplicationInfo(firebaseApp),
107119
fakeFetcher,
@@ -112,6 +124,7 @@ class RemoteSettingsTest {
112124
fakeFetcher.responseJSONObject = fetchedResponse
113125
remoteSettings.updateSettings()
114126

127+
// runCurrent()
115128
assertThat(remoteSettings.sessionEnabled).isFalse()
116129
assertThat(remoteSettings.samplingRate).isEqualTo(0.75)
117130
assertThat(remoteSettings.sessionRestartTimeout).isEqualTo(40.minutes)
@@ -134,7 +147,7 @@ class RemoteSettingsTest {
134147
}
135148

136149
@Test
137-
fun RemoteSettings_successfulFetchWithEmptyConfigRetainsOldConfigs() {
150+
fun RemoteSettings_successfulFetchWithEmptyConfigRetainsOldConfigs() = runTest {
138151
val firebaseApp = FakeFirebaseApp().firebaseApp
139152
val context = firebaseApp.applicationContext
140153
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -143,6 +156,8 @@ class RemoteSettingsTest {
143156
val remoteSettings =
144157
RemoteSettings(
145158
context,
159+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
160+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
146161
firebaseInstallations,
147162
SessionEvents.getApplicationInfo(firebaseApp),
148163
fakeFetcher,

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SessionCoordinatorTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class SessionCoordinatorTest {
5656
TestSessionEventData.TEST_SESSION_DETAILS,
5757
SessionsSettings(
5858
fakeFirebaseApp.firebaseApp.applicationContext,
59+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
60+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
5961
firebaseInstallations,
6062
SessionEvents.getApplicationInfo(fakeFirebaseApp.firebaseApp)
6163
),

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SessionEventEncoderTest.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ import android.os.Build
2020
import androidx.test.ext.junit.runners.AndroidJUnit4
2121
import com.google.common.truth.Truth.assertThat
2222
import com.google.firebase.FirebaseApp
23+
import com.google.firebase.concurrent.TestOnlyExecutors
2324
import com.google.firebase.sessions.SessionEvents.SESSION_EVENT_ENCODER
2425
import com.google.firebase.sessions.settings.SessionsSettings
2526
import com.google.firebase.sessions.testing.FakeFirebaseApp
2627
import com.google.firebase.sessions.testing.FakeFirebaseInstallations
2728
import com.google.firebase.sessions.testing.FakeTimeProvider
2829
import com.google.firebase.sessions.testing.TestSessionEventData
30+
import kotlinx.coroutines.asCoroutineDispatcher
31+
import kotlinx.coroutines.test.runTest
2932
import org.junit.After
3033
import org.junit.Test
3134
import org.junit.runner.RunWith
@@ -39,7 +42,7 @@ class SessionEventEncoderTest {
3942
}
4043

4144
@Test
42-
fun sessionEvent_encodesToJson() {
45+
fun sessionEvent_encodesToJson() = runTest {
4346
val fakeFirebaseApp = FakeFirebaseApp()
4447
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
4548
val sessionEvent =
@@ -48,6 +51,8 @@ class SessionEventEncoderTest {
4851
TestSessionEventData.TEST_SESSION_DETAILS,
4952
SessionsSettings(
5053
fakeFirebaseApp.firebaseApp.applicationContext,
54+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
55+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
5156
firebaseInstallations,
5257
SessionEvents.getApplicationInfo(fakeFirebaseApp.firebaseApp)
5358
),

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SessionEventTest.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.google.firebase.sessions
1919
import android.os.Bundle
2020
import com.google.common.truth.Truth.assertThat
2121
import com.google.firebase.FirebaseApp
22+
import com.google.firebase.concurrent.TestOnlyExecutors
2223
import com.google.firebase.sessions.settings.SessionsSettings
2324
import com.google.firebase.sessions.testing.FakeFirebaseApp
2425
import com.google.firebase.sessions.testing.FakeFirebaseInstallations
@@ -27,6 +28,8 @@ import com.google.firebase.sessions.testing.TestSessionEventData.TEST_DATA_COLLE
2728
import com.google.firebase.sessions.testing.TestSessionEventData.TEST_SESSION_DATA
2829
import com.google.firebase.sessions.testing.TestSessionEventData.TEST_SESSION_DETAILS
2930
import com.google.firebase.sessions.testing.TestSessionEventData.TEST_SESSION_EVENT
31+
import kotlinx.coroutines.asCoroutineDispatcher
32+
import kotlinx.coroutines.test.runTest
3033
import org.junit.After
3134
import org.junit.Test
3235
import org.junit.runner.RunWith
@@ -35,7 +38,7 @@ import org.robolectric.RobolectricTestRunner
3538
@RunWith(RobolectricTestRunner::class)
3639
class SessionEventTest {
3740
@Test
38-
fun sessionStart_populatesSessionDetailsCorrectly() {
41+
fun sessionStart_populatesSessionDetailsCorrectly() = runTest {
3942
val fakeFirebaseApp = FakeFirebaseApp()
4043
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
4144
val sessionEvent =
@@ -44,6 +47,8 @@ class SessionEventTest {
4447
TEST_SESSION_DETAILS,
4548
SessionsSettings(
4649
fakeFirebaseApp.firebaseApp.applicationContext,
50+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
51+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
4752
firebaseInstallations,
4853
SessionEvents.getApplicationInfo(fakeFirebaseApp.firebaseApp)
4954
),
@@ -54,7 +59,7 @@ class SessionEventTest {
5459
}
5560

5661
@Test
57-
fun sessionStart_samplingRate() {
62+
fun sessionStart_samplingRate() = runTest {
5863
val metadata = Bundle()
5964
metadata.putDouble("firebase_sessions_sampling_rate", 0.5)
6065
val fakeFirebaseApp = FakeFirebaseApp(metadata)
@@ -66,6 +71,8 @@ class SessionEventTest {
6671
TEST_SESSION_DETAILS,
6772
SessionsSettings(
6873
fakeFirebaseApp.firebaseApp.applicationContext,
74+
TestOnlyExecutors.blocking().asCoroutineDispatcher() + coroutineContext,
75+
TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext,
6976
firebaseInstallations,
7077
SessionEvents.getApplicationInfo(fakeFirebaseApp.firebaseApp)
7178
),

0 commit comments

Comments
 (0)