Skip to content

Commit fd45f86

Browse files
authored
Remove installations ID from Identifiers and move it to SessionCoordinator (#10545)
1 parent 42d4a06 commit fd45f86

9 files changed

+41
-99
lines changed

FirebaseSessions/Sources/FirebaseSessions.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ protocol SessionsProvider {
5454

5555
let fireLogger = EventGDTLogger(googleDataTransport: googleDataTransport!)
5656

57-
let identifiers = Identifiers(installations: installations)
57+
let identifiers = Identifiers()
5858
let coordinator = SessionCoordinator(
5959
identifiers: identifiers,
60+
installations: installations,
6061
fireLogger: fireLogger,
6162
sampler: SessionSampler()
6263
)

FirebaseSessions/Sources/FirebaseSessionsError.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@ import Foundation
1818
enum FirebaseSessionsError: Error {
1919
/// Event sampling related error
2020
case SessionSamplingError
21+
/// Firebase Installation ID related error
22+
case SessionInstallationsError
2123
}

FirebaseSessions/Sources/Identifiers.swift

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ import Foundation
1818
@_implementationOnly import FirebaseInstallations
1919

2020
protocol IdentifierProvider {
21-
var installationID: String {
22-
get
23-
}
24-
2521
var sessionID: String {
2622
get
2723
}
@@ -39,61 +35,16 @@ protocol IdentifierProvider {
3935
/// (Maybe) 4) Persisting, reading, and incrementing an increasing index
4036
///
4137
class Identifiers: IdentifierProvider {
42-
private let installations: InstallationsProtocol
43-
4438
private var _sessionID: String?
4539
private var _previousSessionID: String?
4640

47-
init(installations: InstallationsProtocol) {
48-
self.installations = installations
49-
}
50-
5141
// Generates a new Session ID. If there was already a generated Session ID
5242
// from the last session during the app's lifecycle, it will also set the last Session ID
5343
func generateNewSessionID() {
5444
_previousSessionID = _sessionID
5545
_sessionID = UUID().uuidString.replacingOccurrences(of: "-", with: "").lowercased()
5646
}
5747

58-
// Fetches the Installation ID from Firebase Installation Service. This method must be run on a background thread due to how Firebase Installations
59-
// handles threading.
60-
var installationID: String {
61-
if Thread.isMainThread {
62-
Logger
63-
.logError(
64-
"Error: Identifiers.installationID getter must be called on a background thread. Using an empty ID"
65-
)
66-
return ""
67-
}
68-
69-
var localInstallationID = ""
70-
71-
let semaphore = DispatchSemaphore(value: 0)
72-
73-
installations.installationID { result in
74-
switch result {
75-
case let .success(fiid):
76-
localInstallationID = fiid
77-
case let .failure(error):
78-
Logger
79-
.logError(
80-
"Error getting Firebase Installation ID: \(error). Using an empty ID"
81-
)
82-
}
83-
84-
semaphore.signal()
85-
}
86-
87-
switch semaphore.wait(timeout: DispatchTime.now() + 1.0) {
88-
case .success:
89-
break
90-
case .timedOut:
91-
Logger.logError("Error: took too long to get the Firebase Installation ID. Using an empty ID")
92-
}
93-
94-
return localInstallationID
95-
}
96-
9748
var sessionID: String {
9849
guard let _sessionID = _sessionID else {
9950
Logger.logError("Error: Sessions SDK did not generate a Session ID")

FirebaseSessions/Sources/SessionCoordinator.swift

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,51 @@ import Foundation
2020
///
2121
class SessionCoordinator {
2222
let identifiers: IdentifierProvider
23+
let installations: InstallationsProtocol
2324
let fireLogger: EventGDTLoggerProtocol
2425
let sampler: SessionSamplerProtocol
2526

26-
init(identifiers: IdentifierProvider, fireLogger: EventGDTLoggerProtocol,
27+
init(identifiers: IdentifierProvider,
28+
installations: InstallationsProtocol,
29+
fireLogger: EventGDTLoggerProtocol,
2730
sampler: SessionSamplerProtocol) {
2831
self.identifiers = identifiers
32+
self.installations = installations
2933
self.fireLogger = fireLogger
3034
self.sampler = sampler
3135
}
3236

3337
// Begins the process of logging a SessionStartEvent to FireLog, while taking into account Data Collection, Sampling, and fetching Settings
3438
func attemptLoggingSessionStart(event: SessionStartEvent,
3539
callback: @escaping (Result<Void, Error>) -> Void) {
40+
/// Order of execution
41+
/// 1. Check if the session can be sent. If yes, move to 2. Else, drop the event.
42+
/// 2. Fetch the installations Id. If successful, move to 3. Else, drop sending the event.
43+
/// 3. Log the event. If successful, all is good. Else, log the message with error.
3644
if sampler.shouldSendEventForSession(sessionId: identifiers.sessionID) {
37-
event.setInstallationID(identifiers: identifiers)
38-
39-
fireLogger.logEvent(event: event) { result in
45+
installations.installationID { result in
4046
switch result {
41-
case .success():
42-
Logger.logInfo("Successfully logged Session Start event to GoogleDataTransport")
43-
callback(.success(()))
47+
case let .success(fiid):
48+
event.setInstallationID(installationId: fiid)
49+
self.fireLogger.logEvent(event: event) { logResult in
50+
switch logResult {
51+
case .success():
52+
Logger.logInfo("Successfully logged Session Start event to GoogleDataTransport")
53+
callback(.success(()))
54+
case let .failure(error):
55+
Logger
56+
.logError(
57+
"Error logging Session Start event to GoogleDataTransport: \(error)."
58+
)
59+
callback(.failure(error))
60+
}
61+
}
4462
case let .failure(error):
4563
Logger
4664
.logError(
47-
"Error logging Session Start event to GoogleDataTransport: \(error)."
65+
"Error getting Firebase Installation ID: \(error). Skip sending event."
4866
)
49-
callback(.failure(error))
67+
callback(.failure(FirebaseSessionsError.SessionInstallationsError))
5068
}
5169
}
5270
} else {

FirebaseSessions/Sources/SessionStartEvent.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ class SessionStartEvent: NSObject, GDTCOREventDataObject {
6060
.performance = firebase_appquality_sessions_DataCollectionState_COLLECTION_UNKNOWN
6161
}
6262

63-
func setInstallationID(identifiers: IdentifierProvider) {
64-
proto.session_data.firebase_installation_id = makeProtoString(identifiers.installationID)
63+
func setInstallationID(installationId: String) {
64+
proto.session_data.firebase_installation_id = makeProtoString(installationId)
6565
}
6666

6767
func setSamplingRate(samplingRate: Double) {

FirebaseSessions/Tests/Unit/IdentifiersTests.swift

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
import XCTest
1717

1818
@testable import FirebaseSessions
19-
@testable import FirebaseInstallations
2019

2120
class IdentifiersTests: XCTestCase {
22-
var installations: MockInstallationsProtocol!
2321
var identifiers: Identifiers!
2422

2523
override func setUp() {
@@ -28,8 +26,7 @@ class IdentifiersTests: XCTestCase {
2826
UserDefaults.standard.removePersistentDomain(forName: appDomain)
2927
}
3028

31-
installations = MockInstallationsProtocol()
32-
identifiers = Identifiers(installations: installations)
29+
identifiers = Identifiers()
3330
}
3431

3532
func isValidSessionID(_ sessionID: String) -> Bool {
@@ -78,34 +75,4 @@ class IdentifiersTests: XCTestCase {
7875
// Ensure the new lastSessionID is equal to the sessionID from earlier
7976
XCTAssertEqual(identifiers.previousSessionID, firstSessionID)
8077
}
81-
82-
// Fetching FIIDs requires that we are on a background thread.
83-
func test_installationID_getsValidID() throws {
84-
// Make our mock return an ID
85-
let testID = "testID"
86-
installations.result = .success(testID)
87-
88-
let expectation = XCTestExpectation(description: "Get the Installation ID Asynchronously")
89-
90-
DispatchQueue.global().async { [self] in
91-
XCTAssertEqual(self.identifiers.installationID, testID)
92-
expectation.fulfill()
93-
}
94-
95-
wait(for: [expectation], timeout: 1.0)
96-
}
97-
98-
func test_installationID_handlesFailedFetch() throws {
99-
// Make our mock return an error
100-
installations.result = .failure(NSError(domain: "FestFailedFIIDErrorDomain", code: 0))
101-
102-
let expectation = XCTestExpectation(description: "Get the Installation ID Asynchronously")
103-
104-
DispatchQueue.global().async { [self] in
105-
XCTAssertEqual(self.identifiers.installationID, "")
106-
expectation.fulfill()
107-
}
108-
109-
wait(for: [expectation], timeout: 1.0)
110-
}
11178
}

FirebaseSessions/Tests/Unit/Mocks/MockInstallationsProtocol.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import FirebaseInstallations
1818
@testable import FirebaseSessions
1919

2020
class MockInstallationsProtocol: InstallationsProtocol {
21-
var result: Result<String, Error> = .success("adsgsadg")
21+
static let testInstallationId = "testInstallationId"
22+
var result: Result<String, Error> = .success(testInstallationId)
2223

2324
func installationID(completion: @escaping (Result<String, Error>) -> Void) {
2425
completion(result)

FirebaseSessions/Tests/Unit/SessionCoordinatorTests.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import XCTest
1919

2020
class SessionCoordinatorTests: XCTestCase {
2121
var identifiers = MockIdentifierProvider()
22+
var installations = MockInstallationsProtocol()
2223
var time = MockTimeProvider()
2324
var fireLogger = MockGDTLogger()
2425
var appInfo = MockApplicationInfo()
@@ -31,6 +32,7 @@ class SessionCoordinatorTests: XCTestCase {
3132

3233
coordinator = SessionCoordinator(
3334
identifiers: identifiers,
35+
installations: installations,
3436
fireLogger: fireLogger,
3537
sampler: sampler
3638
)
@@ -53,7 +55,7 @@ class SessionCoordinatorTests: XCTestCase {
5355
// Make sure we've set the Installation ID
5456
assertEqualProtoString(
5557
event.proto.session_data.firebase_installation_id,
56-
expected: MockIdentifierProvider.testInstallationID,
58+
expected: MockInstallationsProtocol.testInstallationId,
5759
fieldName: "installation_id"
5860
)
5961

@@ -82,7 +84,7 @@ class SessionCoordinatorTests: XCTestCase {
8284
// Make sure we've set the Installation ID
8385
assertEqualProtoString(
8486
event.proto.session_data.firebase_installation_id,
85-
expected: MockIdentifierProvider.testInstallationID,
87+
expected: MockInstallationsProtocol.testInstallationId,
8688
fieldName: "installation_id"
8789
)
8890

FirebaseSessions/Tests/Unit/SessionStartEventTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class SessionStartEventTests: XCTestCase {
111111
identifiers.mockAllValidIDs()
112112

113113
let event = SessionStartEvent(identifiers: identifiers, appInfo: appInfo, time: time)
114-
event.setInstallationID(identifiers: identifiers)
114+
event.setInstallationID(installationId: "testInstallationID")
115115

116116
testProtoAndDecodedProto(sessionEvent: event) { proto in
117117
assertEqualProtoString(

0 commit comments

Comments
 (0)