Skip to content

Commit ecd3043

Browse files
authored
Reorganize Sessions settings (#10599)
1 parent fda7816 commit ecd3043

13 files changed

+459
-125
lines changed

FirebaseSessions/Sources/FirebaseSessions.swift

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protocol SessionsProvider {
4040
private let initiator: SessionInitiator
4141
private let identifiers: Identifiers
4242
private let appInfo: ApplicationInfo
43-
private let settings: SettingsProtocol
43+
private let settings: SessionsSettings
4444

4545
// MARK: - Initializers
4646

@@ -63,13 +63,9 @@ protocol SessionsProvider {
6363
)
6464
let initiator = SessionInitiator()
6565
let appInfo = ApplicationInfo(appID: appID)
66-
let settings = Settings(
66+
let settings = SessionsSettings(
6767
appInfo: appInfo,
68-
downloader: SettingsDownloader(
69-
appInfo: appInfo,
70-
identifiers: identifiers,
71-
installations: installations
72-
)
68+
installations: installations
7369
)
7470

7571
self.init(appID: appID,
@@ -82,7 +78,7 @@ protocol SessionsProvider {
8278

8379
// Initializes the SDK and begines the process of listening for lifecycle events and logging events
8480
init(appID: String, identifiers: Identifiers, coordinator: SessionCoordinator,
85-
initiator: SessionInitiator, appInfo: ApplicationInfo, settings: SettingsProtocol) {
81+
initiator: SessionInitiator, appInfo: ApplicationInfo, settings: SessionsSettings) {
8682
self.appID = appID
8783

8884
self.identifiers = identifiers
@@ -95,7 +91,7 @@ protocol SessionsProvider {
9591

9692
self.initiator.beginListening {
9793
// On each session start, first update Settings if expired
98-
self.settings.fetchAndCacheSettings()
94+
self.settings.updateSettings()
9995
self.identifiers.generateNewSessionID()
10096
let event = SessionStartEvent(identifiers: self.identifiers, appInfo: self.appInfo)
10197
DispatchQueue.global().async {

FirebaseSessions/Sources/SessionLocalConfig.swift renamed to FirebaseSessions/Sources/Settings/LocalOverrideSettings.swift

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,41 @@
1515

1616
import Foundation
1717

18-
/// Protoco defining the loval override values for the SDK settings.
19-
protocol SessionLocalConfigProtocol {
20-
/// Session enabled flag value.
21-
var sessionEnabled: Bool? { get }
22-
23-
/// Session timeout flag value.
24-
var sessionTimeout: TimeInterval? { get }
25-
26-
/// Session timeout flag value.
27-
var sessionSamplingRate: Double? { get }
28-
}
29-
3018
/// Class that manages the local overrides configs related to the library.
31-
class SessionLocalConfig: SessionLocalConfigProtocol {
19+
class LocalOverrideSettings: SettingsProvider, SettingsProtocol {
3220
static let PlistKey_sessions_enabled = "FirebaseSessionsEnabled"
3321
static let PlistKey_sessions_timeout = "FirebaseSessionsTimeout"
3422
static let PlistKey_sessions_samplingRate = "FirebaseSessionsSampingRate"
3523

36-
var sessionEnabled: Bool? {
37-
return plistValueForConfig(configName: SessionLocalConfig.PlistKey_sessions_enabled) as? Bool
24+
var sessionsEnabled: Bool? {
25+
return plistValueForConfig(configName: LocalOverrideSettings.PlistKey_sessions_enabled) as? Bool
3826
}
3927

4028
var sessionTimeout: TimeInterval? {
4129
return
42-
plistValueForConfig(configName: SessionLocalConfig.PlistKey_sessions_timeout) as? TimeInterval
30+
plistValueForConfig(configName: LocalOverrideSettings
31+
.PlistKey_sessions_timeout) as? TimeInterval
4332
}
4433

45-
var sessionSamplingRate: Double? {
34+
var samplingRate: Double? {
4635
return
47-
plistValueForConfig(configName: SessionLocalConfig.PlistKey_sessions_samplingRate) as? Double
36+
plistValueForConfig(configName: LocalOverrideSettings
37+
.PlistKey_sessions_samplingRate) as? Double
4838
}
4939

5040
private func plistValueForConfig(configName: String) -> Any? {
51-
return Bundle.main.value(forKey: configName)
41+
return Bundle.main.object(forInfoDictionaryKey: configName)
42+
}
43+
}
44+
45+
typealias LocalOverrideSettingsProvider = LocalOverrideSettings
46+
extension LocalOverrideSettingsProvider {
47+
func updateSettings() {
48+
// Nothing to be done since there is nothing to be updated.
49+
}
50+
51+
func isSettingsStale() -> Bool {
52+
// Settings are never stale since all of these are local settings from Plist
53+
return false
5254
}
5355
}

FirebaseSessions/Sources/Settings.swift renamed to FirebaseSessions/Sources/Settings/RemoteSettings.swift

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,7 @@ extension ApplicationInfoProtocol {
2020
var synthesizedVersion: String { return "\(appDisplayVersion) (\(appBuildVersion))" }
2121
}
2222

23-
extension SettingsProtocol {
24-
func fetchAndCacheSettings() {
25-
return fetchAndCacheSettings(currentTime: Date())
26-
}
27-
}
28-
29-
/// Provides the APIs to access Settings and their configuration values
30-
protocol SettingsProtocol {
31-
/// Attempts to fetch settings only if the current cache is expired
32-
func fetchAndCacheSettings(currentTime: Date)
33-
var sessionsEnabled: Bool { get }
34-
var samplingRate: Double { get }
35-
var sessionTimeout: TimeInterval { get }
36-
}
37-
38-
class Settings: SettingsProtocol {
23+
class RemoteSettings: SettingsProvider, SettingsProtocol {
3924
private static let cacheDurationSecondsDefault: TimeInterval = 60 * 60
4025
private static let flagSessionsEnabled = "sessions_enabled"
4126
private static let flagSamplingRate = "sampling_rate"
@@ -46,36 +31,15 @@ class Settings: SettingsProtocol {
4631
private let downloader: SettingsDownloadClient
4732
private var cache: SettingsCacheClient
4833

49-
var sessionsEnabled: Bool {
50-
guard let enabled = sessionsCache[Settings.flagSessionsEnabled] as? Bool else {
51-
return true
52-
}
53-
return enabled
54-
}
55-
56-
var samplingRate: Double {
57-
guard let rate = sessionsCache[Settings.flagSamplingRate] as? Double else {
58-
return 1.0
59-
}
60-
return rate
61-
}
62-
63-
var sessionTimeout: TimeInterval {
64-
guard let timeout = sessionsCache[Settings.flagSessionTimeout] as? Double else {
65-
return 30 * 60
66-
}
67-
return timeout
68-
}
69-
7034
private var cacheDurationSeconds: TimeInterval {
71-
guard let duration = cache.cacheContent[Settings.flagCacheDuration] as? Double else {
72-
return Settings.cacheDurationSecondsDefault
35+
guard let duration = cache.cacheContent[RemoteSettings.flagCacheDuration] as? Double else {
36+
return RemoteSettings.cacheDurationSecondsDefault
7337
}
7438
return duration
7539
}
7640

7741
private var sessionsCache: [String: Any] {
78-
return cache.cacheContent[Settings.flagSessionsCache] as? [String: Any] ?? [:]
42+
return cache.cacheContent[RemoteSettings.flagSessionsCache] as? [String: Any] ?? [:]
7943
}
8044

8145
init(appInfo: ApplicationInfoProtocol,
@@ -86,7 +50,7 @@ class Settings: SettingsProtocol {
8650
self.downloader = downloader
8751
}
8852

89-
func fetchAndCacheSettings(currentTime: Date) {
53+
private func fetchAndCacheSettings(currentTime: Date) {
9054
// Only fetch if cache is expired, otherwise do nothing
9155
guard isCacheExpired(time: currentTime) else {
9256
Logger.logDebug("[Settings] Cache is not expired, no fetch will be made.")
@@ -109,6 +73,36 @@ class Settings: SettingsProtocol {
10973
}
11074
}
11175
}
76+
}
77+
78+
typealias RemoteSettingsConfigurations = RemoteSettings
79+
extension RemoteSettingsConfigurations {
80+
var sessionsEnabled: Bool? {
81+
return sessionsCache[RemoteSettings.flagSessionsEnabled] as? Bool
82+
}
83+
84+
var samplingRate: Double? {
85+
return sessionsCache[RemoteSettings.flagSamplingRate] as? Double
86+
}
87+
88+
var sessionTimeout: TimeInterval? {
89+
return sessionsCache[RemoteSettings.flagSessionTimeout] as? Double
90+
}
91+
}
92+
93+
typealias RemoteSettingsProvider = RemoteSettings
94+
extension RemoteSettingsConfigurations {
95+
func updateSettings(currentTime: Date) {
96+
fetchAndCacheSettings(currentTime: currentTime)
97+
}
98+
99+
func updateSettings() {
100+
updateSettings(currentTime: Date())
101+
}
102+
103+
func isSettingsStale() -> Bool {
104+
return isCacheExpired(time: Date())
105+
}
112106

113107
private func isCacheExpired(time: Date) -> Bool {
114108
guard !cache.cacheContent.isEmpty else {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// Copyright 2022 Google LLC
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
import Foundation
17+
18+
/// Class that manages the local overrides configs related to the library.
19+
class SDKDefaultSettings: SettingsProvider, SettingsProtocol {
20+
var sessionsEnabled: Bool? {
21+
// Default is sessions enabled
22+
return true
23+
}
24+
25+
var sessionTimeout: TimeInterval? {
26+
// Default is 30 minutes
27+
return 30 * 60
28+
}
29+
30+
var samplingRate: Double? {
31+
// Default is all events are dispatched
32+
return 1.0
33+
}
34+
}
35+
36+
typealias SDKDefaultSettingsProvider = SDKDefaultSettings
37+
extension SDKDefaultSettingsProvider {
38+
func updateSettings() {
39+
// Nothing to be done since there is nothing to be updated.
40+
}
41+
42+
func isSettingsStale() -> Bool {
43+
// Settings are never stale since all of these are local settings from Plist
44+
return false
45+
}
46+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// Copyright 2022 Google LLC
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
import Foundation
17+
18+
/// Class that manages the configs related to the settings library
19+
class SessionsSettings {
20+
private let appInfo: ApplicationInfoProtocol
21+
private let installations: InstallationsProtocol
22+
private let sdkDefaults: SDKDefaultSettings
23+
private let localOverrides: LocalOverrideSettings
24+
private let remoteSettings: RemoteSettings
25+
26+
convenience init(appInfo: ApplicationInfoProtocol, installations: InstallationsProtocol) {
27+
self.init(appInfo: appInfo,
28+
installations: installations,
29+
sdkDefaults: SDKDefaultSettings(),
30+
localOverrides: LocalOverrideSettings(),
31+
remoteSettings: RemoteSettings(appInfo: appInfo,
32+
downloader: SettingsDownloader(appInfo: appInfo,
33+
installations: installations)))
34+
}
35+
36+
init(appInfo: ApplicationInfoProtocol,
37+
installations: InstallationsProtocol,
38+
sdkDefaults: SDKDefaultSettings,
39+
localOverrides: LocalOverrideSettings,
40+
remoteSettings: RemoteSettings) {
41+
self.appInfo = appInfo
42+
self.installations = installations
43+
self.sdkDefaults = sdkDefaults
44+
self.localOverrides = localOverrides
45+
self.remoteSettings = remoteSettings
46+
}
47+
48+
var sessionsEnabled: Bool {
49+
// Order of precendence LocalOverrides > Remote Settings > SDK Defaults
50+
if let sessionEnabled = localOverrides.sessionsEnabled {
51+
return sessionEnabled
52+
} else if let sessionEnabled = remoteSettings.sessionsEnabled {
53+
return sessionEnabled
54+
}
55+
return sdkDefaults.sessionsEnabled!
56+
}
57+
58+
var sessionTimeout: TimeInterval {
59+
// Order of precendence LocalOverrides > Remote Settings > SDK Defaults
60+
if let sessionTimeout = localOverrides.sessionTimeout {
61+
return sessionTimeout
62+
} else if let sessionTimeout = remoteSettings.sessionTimeout {
63+
return sessionTimeout
64+
}
65+
return sdkDefaults.sessionTimeout!
66+
}
67+
68+
var samplingRate: Double {
69+
// Order of precendence LocalOverrides > Remote Settings > SDK Defaults
70+
if let samplingRate = localOverrides.samplingRate {
71+
return samplingRate
72+
} else if let samplingRate = remoteSettings.samplingRate {
73+
return samplingRate
74+
}
75+
return sdkDefaults.samplingRate!
76+
}
77+
78+
func updateSettings() {
79+
// Update the settings for all the settings providers
80+
sdkDefaults.updateSettings()
81+
remoteSettings.updateSettings()
82+
localOverrides.updateSettings()
83+
}
84+
}

FirebaseSessions/Sources/SettingsDownloadClient.swift renamed to FirebaseSessions/Sources/Settings/SettingsDownloadClient.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,10 @@ protocol SettingsDownloadClient {
2727

2828
class SettingsDownloader: SettingsDownloadClient {
2929
private let appInfo: ApplicationInfoProtocol
30-
private let identifiers: IdentifierProvider
3130
private let installations: InstallationsProtocol
3231

33-
init(appInfo: ApplicationInfoProtocol, identifiers: IdentifierProvider,
34-
installations: InstallationsProtocol) {
32+
init(appInfo: ApplicationInfoProtocol, installations: InstallationsProtocol) {
3533
self.appInfo = appInfo
36-
self.identifiers = identifiers
3734
self.installations = installations
3835
}
3936

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// Copyright 2022 Google LLC
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
import Foundation
17+
18+
/// Provides the APIs to access Settings and their configuration values
19+
protocol SettingsProtocol {
20+
// Config to show if sessions is enabled
21+
var sessionsEnabled: Bool? { get }
22+
23+
// Config showing the sampling rate for sessions
24+
25+
var samplingRate: Double? { get }
26+
27+
// Background timeout config value before which a new session is generated
28+
var sessionTimeout: TimeInterval? { get }
29+
}

0 commit comments

Comments
 (0)