From 720486fe4cd1794f8b1aa2008511d7ab10a8d912 Mon Sep 17 00:00:00 2001 From: scannillo <35243507+scannillo@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:44:17 -0500 Subject: [PATCH] Analytics - only fetch config before flushing events cache (#1337) * Only retrieve config when flushing cache, not per sendEvent analytics call --- CHANGELOG.md | 4 + .../Analytics/BTAnalyticsService.swift | 73 +++++++++---------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7027c9ae50..ec3f4c87e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Braintree iOS SDK Release Notes +## unreleased +* BraintreeCore + * For analytics, only call `fetchOrReturnRemoteConfig()` when batch uploading, not on each analytic event enqueue + ## 6.21.0 (2024-06-12) * BraintreePayPal * Add PayPal App Switch vault flow (BETA) diff --git a/Sources/BraintreeCore/Analytics/BTAnalyticsService.swift b/Sources/BraintreeCore/Analytics/BTAnalyticsService.swift index 694e8d800a..198b2e6239 100644 --- a/Sources/BraintreeCore/Analytics/BTAnalyticsService.swift +++ b/Sources/BraintreeCore/Analytics/BTAnalyticsService.swift @@ -103,52 +103,51 @@ class BTAnalyticsService: Equatable { await BTAnalyticsService.events.append(event) - do { - let configuration = try await apiClient.fetchConfiguration() - - // TODO: - Refactor to make HTTP non-optional property and instantiate in init() - if self.http == nil { - self.http = BTHTTP(authorization: self.apiClient.authorization, customBaseURL: BTAnalyticsService.url) - } - - // A special value passed in by unit tests to prevent BTHTTP from actually posting - if let http = self.http, http.customBaseURL?.absoluteString == "test://do-not-send.url" { - return - } + // TODO: - Refactor to make HTTP non-optional property and instantiate in init() + if self.http == nil { + self.http = BTHTTP(authorization: self.apiClient.authorization, customBaseURL: BTAnalyticsService.url) + } + + // A special value passed in by unit tests to prevent BTHTTP from actually posting + if let http = self.http, http.customBaseURL?.absoluteString == "test://do-not-send.url" { + return + } + + if shouldBypassTimerQueue { + await self.sendQueuedAnalyticsEvents() + return + } + + if BTAnalyticsService.timer == nil { + BTAnalyticsService.timer = DispatchSource.makeTimerSource(queue: self.http?.dispatchQueue) + BTAnalyticsService.timer?.schedule( + deadline: .now() + .seconds(self.timerInterval), + repeating: .seconds(self.timerInterval), + leeway: .seconds(1) + ) - if shouldBypassTimerQueue { - await self.sendQueuedAnalyticsEvents(configuration: configuration) - return - } - - if BTAnalyticsService.timer == nil { - BTAnalyticsService.timer = DispatchSource.makeTimerSource(queue: self.http?.dispatchQueue) - BTAnalyticsService.timer?.schedule( - deadline: .now() + .seconds(self.timerInterval), - repeating: .seconds(self.timerInterval), - leeway: .seconds(1) - ) - - BTAnalyticsService.timer?.setEventHandler { - Task { - await self.sendQueuedAnalyticsEvents(configuration: configuration) - } + BTAnalyticsService.timer?.setEventHandler { + Task { + await self.sendQueuedAnalyticsEvents() } - - BTAnalyticsService.timer?.resume() } - } catch { - return + + BTAnalyticsService.timer?.resume() } } // MARK: - Helpers - func sendQueuedAnalyticsEvents(configuration: BTConfiguration) async { + func sendQueuedAnalyticsEvents() async { if await !BTAnalyticsService.events.isEmpty { - let postParameters = await createAnalyticsEvent(config: configuration, sessionID: apiClient.metadata.sessionID, events: BTAnalyticsService.events.allValues) - http?.post("v1/tracking/batch/events", parameters: postParameters) { _, _, _ in } - await BTAnalyticsService.events.removeAll() + do { + let configuration = try await apiClient.fetchConfiguration() + let postParameters = await createAnalyticsEvent(config: configuration, sessionID: apiClient.metadata.sessionID, events: BTAnalyticsService.events.allValues) + http?.post("v1/tracking/batch/events", parameters: postParameters) { _, _, _ in } + await BTAnalyticsService.events.removeAll() + } catch { + return + } } }