From 469c511cf1ed14cd750a62e92a21160874c7e94d Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 14 Aug 2025 13:08:31 +0100 Subject: [PATCH 1/6] Add statistic tracking to background update tasks --- .../WooAnalyticsEvent+BackgroudUpdates.swift | 42 ++++++++ .../Classes/Extensions/UserDefaults+Woo.swift | 1 + .../BackgroundTaskRefreshDispatcher.swift | 95 ++++++++++++++++++- 3 files changed, 136 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift b/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift index d50e4a4aba3..8122634810e 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift @@ -1,16 +1,58 @@ import Foundation +import WooFoundation extension WooAnalyticsEvent { enum BackgroundUpdates { private enum Keys { static let timeTaken = "time_taken" + static let backgroundTimeGranted = "background_time_granted" + static let networkType = "network_type" + static let isExpensiveConnection = "is_expensive_connection" + static let isLowDataMode = "is_low_data_mode" + static let isPowered = "is_powered" + static let batteryLevel = "battery_level" + static let isLowPowerMode = "is_low_power_mode" + static let timeSinceLastRun = "time_since_last_run" + static let completionStatus = "completion_status" } static func dataSynced(timeTaken: TimeInterval) -> WooAnalyticsEvent { WooAnalyticsEvent(statName: .backgroundDataSynced, properties: [Keys.timeTaken: timeTaken]) } + static func dataSyncedDetailed( + timeTaken: TimeInterval, + backgroundTimeGranted: TimeInterval?, + networkType: String, + isExpensiveConnection: Bool, + isLowDataMode: Bool, + isPowered: Bool, + batteryLevel: Float, + isLowPowerMode: Bool, + timeSinceLastRun: TimeInterval? + ) -> WooAnalyticsEvent { + var properties: [String: WooAnalyticsEventPropertyType] = [ + Keys.timeTaken: Int64(timeTaken), + Keys.networkType: networkType, + Keys.isExpensiveConnection: isExpensiveConnection, + Keys.isLowDataMode: isLowDataMode, + Keys.isPowered: isPowered, + Keys.batteryLevel: Float64(batteryLevel), + Keys.isLowPowerMode: isLowPowerMode + ] + + if let backgroundTimeGranted = backgroundTimeGranted { + properties[Keys.backgroundTimeGranted] = Int64(backgroundTimeGranted) + } + + if let timeSinceLastRun = timeSinceLastRun { + properties[Keys.timeSinceLastRun] = Int64(timeSinceLastRun) + } + + return WooAnalyticsEvent(statName: .backgroundDataSynced, properties: properties) + } + static func dataSyncError(_ error: Error) -> WooAnalyticsEvent { WooAnalyticsEvent(statName: .backgroundDataSyncError, properties: [:], error: error) } diff --git a/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift b/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift index 95f9fd27f87..ceeae2c1d7b 100644 --- a/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift +++ b/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift @@ -50,6 +50,7 @@ extension UserDefaults { // Background Task Refresh case latestBackgroundOrderSyncDate + case lastBackgroundRefreshTime // Blaze Local notification case blazeNoCampaignReminderOpened diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift index 4f1cab73b73..dee4e0a20de 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift @@ -1,6 +1,7 @@ import UIKit import Foundation import BackgroundTasks +import Network final class BackgroundTaskRefreshDispatcher { @@ -54,6 +55,10 @@ final class BackgroundTaskRefreshDispatcher { return } + // Capture system state at start + let systemInfo = BackgroundTaskSystemInfo() + let lastRunTime = UserDefaults.standard[.lastBackgroundRefreshTime] as? Date + // Schedule a new refresh task. scheduleAppRefresh() @@ -78,7 +83,24 @@ final class BackgroundTaskRefreshDispatcher { } let timeTaken = round(Date.now.timeIntervalSince(startTime)) - ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSynced(timeTaken: timeTaken)) + let timeSinceLastRun = lastRunTime?.timeIntervalSinceNow.magnitude + + // Track detailed analytics + ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSyncedDetailed( + timeTaken: timeTaken, + backgroundTimeGranted: systemInfo.backgroundTimeGranted, + networkType: systemInfo.networkType, + isExpensiveConnection: systemInfo.isExpensiveConnection, + isLowDataMode: systemInfo.isLowDataMode, + isPowered: systemInfo.isPowered, + batteryLevel: systemInfo.batteryLevel, + isLowPowerMode: systemInfo.isLowPowerMode, + timeSinceLastRun: timeSinceLastRun + )) + + // Update last run timestamp + UserDefaults.standard[.lastBackgroundRefreshTime] = Date() + backgroundTask.setTaskCompleted(success: true) } catch { @@ -93,7 +115,7 @@ final class BackgroundTaskRefreshDispatcher { ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSyncError(BackgroundError.expired)) refreshTasks.cancel() } - } + } } private extension BackgroundTaskRefreshDispatcher { @@ -109,3 +131,72 @@ extension BackgroundTaskRefreshDispatcher { case expired } } + +// MARK: - System Information Helper + +private struct NetworkInfo { + let type: String + let isExpensive: Bool + let isLowDataMode: Bool +} + +private struct BackgroundTaskSystemInfo { + let backgroundTimeGranted: TimeInterval? + let networkInfo: NetworkInfo + let isPowered: Bool + let batteryLevel: Float + let isLowPowerMode: Bool + + // Computed properties for clean external access + var networkType: String { networkInfo.type } + var isExpensiveConnection: Bool { networkInfo.isExpensive } + var isLowDataMode: Bool { networkInfo.isLowDataMode } + + init() { + // Background time granted (nil if foreground/unlimited) + let bgTime = UIApplication.shared.backgroundTimeRemaining + self.backgroundTimeGranted = bgTime < Double.greatestFiniteMagnitude ? bgTime : nil + + // Network info + self.networkInfo = Self.getNetworkInfo() + + // Power and battery info + let device = UIDevice.current + device.isBatteryMonitoringEnabled = true + + self.isPowered = device.batteryState == .charging || device.batteryState == .full + self.batteryLevel = device.batteryLevel + self.isLowPowerMode = ProcessInfo.processInfo.isLowPowerModeEnabled + + device.isBatteryMonitoringEnabled = false + } + + private static func getNetworkInfo() -> NetworkInfo { + let monitor = NWPathMonitor() + let path = monitor.currentPath + + // Check connection status first + guard path.status == .satisfied else { + return NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) + } + + let isExpensive = path.isExpensive + let isLowDataMode = path.isConstrained + + // Determine connection type + let networkType: String + if path.usesInterfaceType(.wifi) { + networkType = "wifi" + } else if path.usesInterfaceType(.cellular) { + networkType = "cellular" + } else if path.usesInterfaceType(.wiredEthernet) { + networkType = "ethernet" + } else if path.usesInterfaceType(.loopback) { + networkType = "loopback" + } else { + networkType = "other" + } + + return NetworkInfo(type: networkType, isExpensive: isExpensive, isLowDataMode: isLowDataMode) + } +} From f3ef9be4c27a30b9a94c58fafea8fa852d21f3c0 Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 14 Aug 2025 13:13:50 +0100 Subject: [PATCH 2/6] Fix network info tracking on background tasks --- .../BackgroundTaskRefreshDispatcher.swift | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift index dee4e0a20de..f4021086ede 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift @@ -172,31 +172,47 @@ private struct BackgroundTaskSystemInfo { } private static func getNetworkInfo() -> NetworkInfo { + // Use a semaphore to wait for the path update + let semaphore = DispatchSemaphore(value: 0) let monitor = NWPathMonitor() - let path = monitor.currentPath - - // Check connection status first - guard path.status == .satisfied else { - return NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) - } - - let isExpensive = path.isExpensive - let isLowDataMode = path.isConstrained - - // Determine connection type - let networkType: String - if path.usesInterfaceType(.wifi) { - networkType = "wifi" - } else if path.usesInterfaceType(.cellular) { - networkType = "cellular" - } else if path.usesInterfaceType(.wiredEthernet) { - networkType = "ethernet" - } else if path.usesInterfaceType(.loopback) { - networkType = "loopback" - } else { - networkType = "other" + var networkInfo = NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) + + monitor.pathUpdateHandler = { path in + // Check connection status first + guard path.status == .satisfied else { + networkInfo = NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) + semaphore.signal() + return + } + + let isExpensive = path.isExpensive + let isLowDataMode = path.isConstrained + + // Determine connection type + let networkType: String + if path.usesInterfaceType(.wifi) { + networkType = "wifi" + } else if path.usesInterfaceType(.cellular) { + networkType = "cellular" + } else if path.usesInterfaceType(.wiredEthernet) { + networkType = "ethernet" + } else if path.usesInterfaceType(.loopback) { + networkType = "loopback" + } else { + networkType = "other" + } + + networkInfo = NetworkInfo(type: networkType, isExpensive: isExpensive, isLowDataMode: isLowDataMode) + semaphore.signal() } - - return NetworkInfo(type: networkType, isExpensive: isExpensive, isLowDataMode: isLowDataMode) + + let queue = DispatchQueue(label: "network.monitor.queue") + monitor.start(queue: queue) + + // Wait up to 1 second for network info + _ = semaphore.wait(timeout: .now() + 1.0) + monitor.cancel() + + return networkInfo } } From 83770bd44b325912dc82dd662d47162c8c75b18d Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 14 Aug 2025 13:30:43 +0100 Subject: [PATCH 3/6] Use concurrency instead of semaphores for async --- .../BackgroundTaskRefreshDispatcher.swift | 88 +++++++++---------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift index f4021086ede..4209c17b800 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift @@ -55,16 +55,14 @@ final class BackgroundTaskRefreshDispatcher { return } - // Capture system state at start - let systemInfo = BackgroundTaskSystemInfo() - let lastRunTime = UserDefaults.standard[.lastBackgroundRefreshTime] as? Date - // Schedule a new refresh task. scheduleAppRefresh() // Launch all refresh tasks in parallel. let refreshTasks = Task { do { + let systemInfo = await BackgroundTaskSystemInfo() + let lastRunTime = UserDefaults.standard[.lastBackgroundRefreshTime] as? Date let startTime = Date.now @@ -152,13 +150,14 @@ private struct BackgroundTaskSystemInfo { var isExpensiveConnection: Bool { networkInfo.isExpensive } var isLowDataMode: Bool { networkInfo.isLowDataMode } - init() { + @MainActor + init() async { // Background time granted (nil if foreground/unlimited) let bgTime = UIApplication.shared.backgroundTimeRemaining self.backgroundTimeGranted = bgTime < Double.greatestFiniteMagnitude ? bgTime : nil // Network info - self.networkInfo = Self.getNetworkInfo() + self.networkInfo = await Self.getNetworkInfo() // Power and battery info let device = UIDevice.current @@ -171,48 +170,43 @@ private struct BackgroundTaskSystemInfo { device.isBatteryMonitoringEnabled = false } - private static func getNetworkInfo() -> NetworkInfo { - // Use a semaphore to wait for the path update - let semaphore = DispatchSemaphore(value: 0) - let monitor = NWPathMonitor() - var networkInfo = NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) - - monitor.pathUpdateHandler = { path in - // Check connection status first - guard path.status == .satisfied else { - networkInfo = NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) - semaphore.signal() - return - } - - let isExpensive = path.isExpensive - let isLowDataMode = path.isConstrained - - // Determine connection type - let networkType: String - if path.usesInterfaceType(.wifi) { - networkType = "wifi" - } else if path.usesInterfaceType(.cellular) { - networkType = "cellular" - } else if path.usesInterfaceType(.wiredEthernet) { - networkType = "ethernet" - } else if path.usesInterfaceType(.loopback) { - networkType = "loopback" - } else { - networkType = "other" + private static func getNetworkInfo() async -> NetworkInfo { + return await withCheckedContinuation { continuation in + let monitor = NWPathMonitor() + + monitor.pathUpdateHandler = { path in + // Check connection status first + guard path.status == .satisfied else { + let networkInfo = NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) + continuation.resume(returning: networkInfo) + monitor.cancel() + return + } + + let isExpensive = path.isExpensive + let isLowDataMode = path.isConstrained + + // Determine connection type + let networkType: String + if path.usesInterfaceType(.wifi) { + networkType = "wifi" + } else if path.usesInterfaceType(.cellular) { + networkType = "cellular" + } else if path.usesInterfaceType(.wiredEthernet) { + networkType = "ethernet" + } else if path.usesInterfaceType(.loopback) { + networkType = "loopback" + } else { + networkType = "other" + } + + let networkInfo = NetworkInfo(type: networkType, isExpensive: isExpensive, isLowDataMode: isLowDataMode) + continuation.resume(returning: networkInfo) + monitor.cancel() } - - networkInfo = NetworkInfo(type: networkType, isExpensive: isExpensive, isLowDataMode: isLowDataMode) - semaphore.signal() + + let queue = DispatchQueue(label: "network.monitor.queue") + monitor.start(queue: queue) } - - let queue = DispatchQueue(label: "network.monitor.queue") - monitor.start(queue: queue) - - // Wait up to 1 second for network info - _ = semaphore.wait(timeout: .now() + 1.0) - monitor.cancel() - - return networkInfo } } From a35463387f40c5f2cce2b4bd1469fd1715b50401 Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 14 Aug 2025 14:55:01 +0100 Subject: [PATCH 4/6] Tidy up comments and structure --- .../BackgroundTaskRefreshDispatcher.swift | 66 ++++++++++--------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift index 4209c17b800..2b3a2b7b2e8 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift @@ -83,7 +83,6 @@ final class BackgroundTaskRefreshDispatcher { let timeTaken = round(Date.now.timeIntervalSince(startTime)) let timeSinceLastRun = lastRunTime?.timeIntervalSinceNow.magnitude - // Track detailed analytics ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSyncedDetailed( timeTaken: timeTaken, backgroundTimeGranted: systemInfo.backgroundTimeGranted, @@ -96,8 +95,8 @@ final class BackgroundTaskRefreshDispatcher { timeSinceLastRun: timeSinceLastRun )) - // Update last run timestamp - UserDefaults.standard[.lastBackgroundRefreshTime] = Date() + // Save date, for use in analytics next time we refresh + UserDefaults.standard[.lastBackgroundRefreshTime] = Date.now backgroundTask.setTaskCompleted(success: true) @@ -153,8 +152,8 @@ private struct BackgroundTaskSystemInfo { @MainActor init() async { // Background time granted (nil if foreground/unlimited) - let bgTime = UIApplication.shared.backgroundTimeRemaining - self.backgroundTimeGranted = bgTime < Double.greatestFiniteMagnitude ? bgTime : nil + let backgroundTime = UIApplication.shared.backgroundTimeRemaining + self.backgroundTimeGranted = backgroundTime < Double.greatestFiniteMagnitude ? backgroundTime : nil // Network info self.networkInfo = await Self.getNetworkInfo() @@ -175,33 +174,7 @@ private struct BackgroundTaskSystemInfo { let monitor = NWPathMonitor() monitor.pathUpdateHandler = { path in - // Check connection status first - guard path.status == .satisfied else { - let networkInfo = NetworkInfo(type: "no_connection", isExpensive: false, isLowDataMode: false) - continuation.resume(returning: networkInfo) - monitor.cancel() - return - } - - let isExpensive = path.isExpensive - let isLowDataMode = path.isConstrained - - // Determine connection type - let networkType: String - if path.usesInterfaceType(.wifi) { - networkType = "wifi" - } else if path.usesInterfaceType(.cellular) { - networkType = "cellular" - } else if path.usesInterfaceType(.wiredEthernet) { - networkType = "ethernet" - } else if path.usesInterfaceType(.loopback) { - networkType = "loopback" - } else { - networkType = "other" - } - - let networkInfo = NetworkInfo(type: networkType, isExpensive: isExpensive, isLowDataMode: isLowDataMode) - continuation.resume(returning: networkInfo) + continuation.resume(returning: NetworkInfo(path: path)) monitor.cancel() } @@ -210,3 +183,32 @@ private struct BackgroundTaskSystemInfo { } } } + +private extension NetworkInfo { + init(path: NWPath) { + guard path.status == .satisfied else { + self.type = "no_connection" + self.isExpensive = false + self.isLowDataMode = false + return + } + + self.type = Self.networkType(from: path) + self.isExpensive = path.isExpensive + self.isLowDataMode = path.isConstrained + } + + private static func networkType(from path: NWPath) -> String { + if path.usesInterfaceType(.wifi) { + return "wifi" + } else if path.usesInterfaceType(.cellular) { + return "cellular" + } else if path.usesInterfaceType(.wiredEthernet) { + return "ethernet" + } else if path.usesInterfaceType(.loopback) { + return "loopback" + } else { + return "other" + } + } +} From 3ad0806aa9bb637ec5ec628a9f93e56e90f79c8a Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Fri, 15 Aug 2025 11:56:05 +0100 Subject: [PATCH 5/6] Changes from code review --- .../WooAnalyticsEvent+BackgroudUpdates.swift | 7 +------ .../Classes/Extensions/UserDefaults+Woo.swift | 2 +- .../BackgroundTaskRefreshDispatcher.swift | 13 ++++++++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift b/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift index 8122634810e..6439d82e579 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsEvent+BackgroudUpdates.swift @@ -14,14 +14,9 @@ extension WooAnalyticsEvent { static let batteryLevel = "battery_level" static let isLowPowerMode = "is_low_power_mode" static let timeSinceLastRun = "time_since_last_run" - static let completionStatus = "completion_status" } - static func dataSynced(timeTaken: TimeInterval) -> WooAnalyticsEvent { - WooAnalyticsEvent(statName: .backgroundDataSynced, properties: [Keys.timeTaken: timeTaken]) - } - - static func dataSyncedDetailed( + static func dataSynced( timeTaken: TimeInterval, backgroundTimeGranted: TimeInterval?, networkType: String, diff --git a/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift b/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift index ceeae2c1d7b..52e2a86af76 100644 --- a/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift +++ b/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift @@ -50,7 +50,7 @@ extension UserDefaults { // Background Task Refresh case latestBackgroundOrderSyncDate - case lastBackgroundRefreshTime + case lastBackgroundRefreshCompletionTime // Blaze Local notification case blazeNoCampaignReminderOpened diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift index 2b3a2b7b2e8..3e7cb06520e 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift @@ -62,7 +62,6 @@ final class BackgroundTaskRefreshDispatcher { let refreshTasks = Task { do { let systemInfo = await BackgroundTaskSystemInfo() - let lastRunTime = UserDefaults.standard[.lastBackgroundRefreshTime] as? Date let startTime = Date.now @@ -81,9 +80,13 @@ final class BackgroundTaskRefreshDispatcher { } let timeTaken = round(Date.now.timeIntervalSince(startTime)) - let timeSinceLastRun = lastRunTime?.timeIntervalSinceNow.magnitude - ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSyncedDetailed( + var timeSinceLastRun: TimeInterval? = nil + if let lastRunTime = UserDefaults.standard[.lastBackgroundRefreshCompletionTime] as? Date { + timeSinceLastRun = round(lastRunTime.timeIntervalSinceNow.magnitude) + } + + ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSynced( timeTaken: timeTaken, backgroundTimeGranted: systemInfo.backgroundTimeGranted, networkType: systemInfo.networkType, @@ -96,7 +99,7 @@ final class BackgroundTaskRefreshDispatcher { )) // Save date, for use in analytics next time we refresh - UserDefaults.standard[.lastBackgroundRefreshTime] = Date.now + UserDefaults.standard[.lastBackgroundRefreshCompletionTime] = Date.now backgroundTask.setTaskCompleted(success: true) @@ -139,7 +142,7 @@ private struct NetworkInfo { private struct BackgroundTaskSystemInfo { let backgroundTimeGranted: TimeInterval? - let networkInfo: NetworkInfo + private let networkInfo: NetworkInfo let isPowered: Bool let batteryLevel: Float let isLowPowerMode: Bool From 7758a927428cfe57d29726ae37f2411b820a0961 Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Fri, 15 Aug 2025 12:49:47 +0100 Subject: [PATCH 6/6] =?UTF-8?q?Don=E2=80=99t=20wait=20for=20the=20system?= =?UTF-8?q?=20info=20before=20refreshing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BackgroundTasks/BackgroundTaskRefreshDispatcher.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift index 3e7cb06520e..043df4ab1c8 100644 --- a/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift +++ b/WooCommerce/Classes/Tools/BackgroundTasks/BackgroundTaskRefreshDispatcher.swift @@ -61,7 +61,7 @@ final class BackgroundTaskRefreshDispatcher { // Launch all refresh tasks in parallel. let refreshTasks = Task { do { - let systemInfo = await BackgroundTaskSystemInfo() + async let systemInfo = BackgroundTaskSystemInfo() let startTime = Date.now @@ -86,7 +86,7 @@ final class BackgroundTaskRefreshDispatcher { timeSinceLastRun = round(lastRunTime.timeIntervalSinceNow.magnitude) } - ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSynced( + await ServiceLocator.analytics.track(event: .BackgroundUpdates.dataSynced( timeTaken: timeTaken, backgroundTimeGranted: systemInfo.backgroundTimeGranted, networkType: systemInfo.networkType,