-
Notifications
You must be signed in to change notification settings - Fork 578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure the settings cache has loaded from disk before reading any values #5103
Changes from 5 commits
ebcbd95
64a0cda
13f89dd
f222f38
b8e6e76
9982ffc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,10 +16,11 @@ | |
|
||
package com.google.firebase.sessions.settings | ||
|
||
import android.content.Context | ||
import android.os.Build | ||
import android.util.Log | ||
import androidx.datastore.preferences.preferencesDataStore | ||
import androidx.annotation.VisibleForTesting | ||
import androidx.datastore.core.DataStore | ||
import androidx.datastore.preferences.core.Preferences | ||
import com.google.firebase.installations.FirebaseInstallationsApi | ||
import com.google.firebase.sessions.ApplicationInfo | ||
import java.util.concurrent.atomic.AtomicBoolean | ||
|
@@ -33,19 +34,14 @@ import org.json.JSONException | |
import org.json.JSONObject | ||
|
||
internal class RemoteSettings( | ||
context: Context, | ||
blockingDispatcher: CoroutineContext, | ||
private val backgroundDispatcher: CoroutineContext, | ||
private val firebaseInstallationsApi: FirebaseInstallationsApi, | ||
private val appInfo: ApplicationInfo, | ||
private val configsFetcher: CrashlyticsSettingsFetcher = | ||
RemoteSettingsFetcher(appInfo, blockingDispatcher), | ||
dataStoreName: String = SESSION_CONFIGS_NAME, | ||
private val configsFetcher: CrashlyticsSettingsFetcher, | ||
dataStore: DataStore<Preferences>, | ||
) : SettingsProvider { | ||
private val Context.dataStore by | ||
preferencesDataStore(name = dataStoreName, scope = CoroutineScope(backgroundDispatcher)) | ||
private val settingsCache = SettingsCache(context.dataStore) | ||
private var fetchInProgress = AtomicBoolean(false) | ||
private val settingsCache = SettingsCache(dataStore) | ||
private val fetchInProgress = AtomicBoolean(false) | ||
|
||
override val sessionEnabled: Boolean? | ||
get() = settingsCache.sessionsEnabled() | ||
|
@@ -63,6 +59,7 @@ internal class RemoteSettings( | |
|
||
override fun isSettingsStale(): Boolean = settingsCache.hasCacheExpired() | ||
|
||
@VisibleForTesting | ||
internal fun clearCachedSettings() { | ||
val scope = CoroutineScope(backgroundDispatcher) | ||
scope.launch { settingsCache.removeConfigs() } | ||
|
@@ -81,6 +78,7 @@ internal class RemoteSettings( | |
|
||
fetchInProgress.set(true) | ||
|
||
// TODO(mrober): Avoid sending the fid here, and avoid fetching it when data collection is off. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok so I looked in the iOS SDK - the way we handle this is just not kicking off the fetch unless we start sending events. So like where we log the event to FireLog is where we'd also kick off settings fetch (but settings must happen before we check the sampling rate) In the iOS SDK there's a separate method for fetching settings and reading from the cache. Reading from the cache always happens, but fetching happens only when we're cleared to send events There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did something very similar in #5107 |
||
// Get the installations ID before making a remote config fetch | ||
val installationId = firebaseInstallationsApi.id.await() | ||
if (installationId == null) { | ||
|
@@ -155,9 +153,9 @@ internal class RemoteSettings( | |
return s.replace(FORWARD_SLASH_STRING.toRegex(), "") | ||
} | ||
|
||
companion object { | ||
private const val SESSION_CONFIGS_NAME = "firebase_session_settings" | ||
private const val TAG = "SessionConfigFetcher" | ||
private const val FORWARD_SLASH_STRING: String = "/" | ||
private companion object { | ||
const val TAG = "SessionConfigFetcher" | ||
|
||
const val FORWARD_SLASH_STRING: String = "/" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we encapsulate this if statement? To me seeing an if statement with a hanging
.metaData
makes it hard to read what we're getting the.metaData
fromThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit hard to clean this up because if I do any other than inline everything like this, I run into https://youtrack.jetbrains.com/issue/KT-53650
I tried to make it clearer, I moved the .metaData inside the if and else bodies, and added a comment for the default value.