From 4cbae349994839c5e7565d5e94052951dc1e8ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pantale=C3=A3o=20Gon=C3=A7alves?= <5808343+bgoncal@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:33:31 +0100 Subject: [PATCH] Avoid updating database in background (#3436) ## Summary ## Screenshots ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant# ## Any other notes --- HomeAssistant.xcodeproj/project.pbxproj | 4 ---- Sources/App/Scenes/WebViewSceneDelegate.swift | 9 +++++++-- Sources/App/Settings/SettingsRootDataSource.swift | 5 +---- Sources/App/Settings/SettingsViewController.swift | 7 +++++++ Sources/Shared/Environment/AppDatabaseUpdater.swift | 8 +++++--- Sources/Shared/Environment/Environment.swift | 2 +- Sources/Shared/Panels/PanelsUpdater.swift | 7 +++++-- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/HomeAssistant.xcodeproj/project.pbxproj b/HomeAssistant.xcodeproj/project.pbxproj index 93eb9efc3..50ec9f366 100644 --- a/HomeAssistant.xcodeproj/project.pbxproj +++ b/HomeAssistant.xcodeproj/project.pbxproj @@ -587,7 +587,6 @@ 421B1C182BD6524E001ED18C /* WidgetBuilderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421B1C172BD6524E001ED18C /* WidgetBuilderViewModel.swift */; }; 421B1C1D2BD65C04001ED18C /* View+ConditionalModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421B1C1B2BD65BFA001ED18C /* View+ConditionalModifier.swift */; }; 4221ED352D009EF700BAE3EB /* AppDatabaseUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4221ED332D009BD000BAE3EB /* AppDatabaseUpdater.swift */; }; - 4221ED362D009EF700BAE3EB /* AppDatabaseUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4221ED332D009BD000BAE3EB /* AppDatabaseUpdater.swift */; }; 4223688B2D40F9B7005911E4 /* WidgetCustom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4223688A2D40F9B7005911E4 /* WidgetCustom.swift */; }; 4223688E2D40FB00005911E4 /* WidgetCustomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4223688D2D40FB00005911E4 /* WidgetCustomTimelineProvider.swift */; }; 422368902D40FCDE005911E4 /* CustomWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4223688F2D40FCDE005911E4 /* CustomWidget.swift */; }; @@ -835,7 +834,6 @@ 42DD84162B14D7AC00936F16 /* WebViewExternalBusMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DD84142B14D68C00936F16 /* WebViewExternalBusMessage.swift */; }; 42DD84192B14D83B00936F16 /* WebViewExternalBusMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DD84182B14D83B00936F16 /* WebViewExternalBusMessageTests.swift */; }; 42DE75D32D1061A600FF379F /* PanelsUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DE75D12D105F3000FF379F /* PanelsUpdater.swift */; }; - 42DE75D42D1061A600FF379F /* PanelsUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DE75D12D105F3000FF379F /* PanelsUpdater.swift */; }; 42DEDA9A2C5B926400E9D29D /* AppVersionSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DEDA992C5B926400E9D29D /* AppVersionSensor.swift */; }; 42DEDA9B2C5B926400E9D29D /* AppVersionSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DEDA992C5B926400E9D29D /* AppVersionSensor.swift */; }; 42DF6B2D2CCF8A2200D7EC14 /* PermissionRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DF6B2C2CCF8A2200D7EC14 /* PermissionRequestView.swift */; }; @@ -7375,7 +7373,6 @@ 424151FD2CD8F27100D7A6F9 /* CarPlayConfig.swift in Sources */, 113A8D4A283C7B1700B9DA32 /* PeriodicUpdateManager.swift in Sources */, 4264906C2C0F1B60002155CC /* AssistChatItem.swift in Sources */, - 4221ED362D009EF700BAE3EB /* AppDatabaseUpdater.swift in Sources */, 424151FA2CD8EF2200D7A6F9 /* MagicItem+Migration.swift in Sources */, 42070EED2BAC523F0031E96F /* AssistService.swift in Sources */, B6872E642226841400C475D1 /* MobileAppRegistrationRequest.swift in Sources */, @@ -7439,7 +7436,6 @@ 11CFD78227364F450082D557 /* Identifier.swift in Sources */, 11AF4D17249C8083006C74C0 /* With.swift in Sources */, 42333ADB2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */, - 42DE75D42D1061A600FF379F /* PanelsUpdater.swift in Sources */, 11B38EF7275C54A300205C7B /* UpdateSensorsIntentHandler.swift in Sources */, 1141182B24AFA10900E6525C /* WebhookResponseHandler.swift in Sources */, 426266462C11B02C0081A818 /* InteractiveImmediateMessages.swift in Sources */, diff --git a/Sources/App/Scenes/WebViewSceneDelegate.swift b/Sources/App/Scenes/WebViewSceneDelegate.swift index 1bbcfcea0..8d12ed653 100644 --- a/Sources/App/Scenes/WebViewSceneDelegate.swift +++ b/Sources/App/Scenes/WebViewSceneDelegate.swift @@ -125,8 +125,13 @@ final class WebViewSceneDelegate: NSObject, UIWindowSceneDelegate { Current.modelManager.subscribe(isAppInForeground: { UIApplication.shared.applicationState == .active }) - Current.appDatabaseUpdater.update() - Current.panelsUpdater.update() + + Current.appDatabaseUpdater.update { + UIApplication.shared.applicationState + } + Current.panelsUpdater.update { + UIApplication.shared.applicationState + } let widgetsCacheFile = AppConstants.widgetsCacheURL diff --git a/Sources/App/Settings/SettingsRootDataSource.swift b/Sources/App/Settings/SettingsRootDataSource.swift index 8f1822a28..c39d372ca 100644 --- a/Sources/App/Settings/SettingsRootDataSource.swift +++ b/Sources/App/Settings/SettingsRootDataSource.swift @@ -159,7 +159,6 @@ enum SettingsRootDataSource { $0.icon = .watchVariantIcon $0.hidden = .isCatalyst $0.presentationMode = .presentModally(controllerProvider: ControllerProvider.callback { - Current.appDatabaseUpdater.update() let controller = UIHostingController(rootView: WatchConfigurationView()) controller.overrideUserInterfaceStyle = .dark return controller @@ -175,7 +174,6 @@ enum SettingsRootDataSource { $0.icon = .carBackIcon $0.hidden = .isCatalyst $0.presentationMode = .presentModally(controllerProvider: ControllerProvider.callback { - Current.appDatabaseUpdater.update() let controller = UIHostingController(rootView: CarPlayConfigurationView()) controller.overrideUserInterfaceStyle = .dark return controller @@ -214,8 +212,7 @@ enum SettingsRootDataSource { $0.title = L10n.Settings.Widgets.title $0.icon = .widgetsIcon $0.presentationMode = .show(controllerProvider: ControllerProvider.callback { - Current.appDatabaseUpdater.update() - return UIHostingController(rootView: WidgetBuilderView()) + UIHostingController(rootView: WidgetBuilderView()) }, onDismiss: nil) } } diff --git a/Sources/App/Settings/SettingsViewController.swift b/Sources/App/Settings/SettingsViewController.swift index 5e6d2b9f0..d2ae251cc 100644 --- a/Sources/App/Settings/SettingsViewController.swift +++ b/Sources/App/Settings/SettingsViewController.swift @@ -163,6 +163,13 @@ class SettingsViewController: HAFormViewController { <<< SettingsRootDataSource.Row.whatsNew.row } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + Current.appDatabaseUpdater.update { + UIApplication.shared.applicationState + } + } + @objc func openAbout(_ sender: UIButton) { let aboutView = AboutViewController() diff --git a/Sources/Shared/Environment/AppDatabaseUpdater.swift b/Sources/Shared/Environment/AppDatabaseUpdater.swift index 59da084e5..2bfffb43b 100644 --- a/Sources/Shared/Environment/AppDatabaseUpdater.swift +++ b/Sources/Shared/Environment/AppDatabaseUpdater.swift @@ -1,10 +1,11 @@ import Foundation import GRDB import HAKit +import UIKit public protocol AppDatabaseUpdaterProtocol { func stop() - func update() + func update(uiApplicationState: @escaping () -> UIApplication.State) } final class AppDatabaseUpdater: AppDatabaseUpdaterProtocol { @@ -17,7 +18,7 @@ final class AppDatabaseUpdater: AppDatabaseUpdaterProtocol { cancelOnGoingRequests() } - func update() { + func update(uiApplicationState: @escaping () -> UIApplication.State) { cancelOnGoingRequests() if let lastUpdate, lastUpdate.timeIntervalSinceNow > -5 { @@ -30,13 +31,13 @@ final class AppDatabaseUpdater: AppDatabaseUpdaterProtocol { Current.Log.verbose("Updating database, servers count \(Current.servers.all.count)") Current.servers.all.forEach { server in guard server.info.connection.activeURL() != nil else { return } - // Cache entities let requestToken = Current.api(for: server)?.connection.send( HATypedRequest<[HAEntity]>.fetchStates(), completion: { result in switch result { case let .success(entities): + guard uiApplicationState() == .active else { return } Current.appEntitiesModel().updateModel(Set(entities), server: server) case let .failure(error): Current.Log.error("Failed to fetch states: \(error)") @@ -58,6 +59,7 @@ final class AppDatabaseUpdater: AppDatabaseUpdaterProtocol { completion: { [weak self] result in switch result { case let .success(response): + guard uiApplicationState() == .active else { return } self?.saveEntityRegistryListForDisplay(response, serverId: server.identifier.rawValue) case let .failure(error): Current.Log.error("Failed to fetch EntityRegistryListForDisplay: \(error)") diff --git a/Sources/Shared/Environment/Environment.swift b/Sources/Shared/Environment/Environment.swift index 162a1bb49..a820459b5 100644 --- a/Sources/Shared/Environment/Environment.swift +++ b/Sources/Shared/Environment/Environment.swift @@ -118,11 +118,11 @@ public class AppEnvironment { AppEntitiesModel.shared } + #if os(iOS) public var appDatabaseUpdater: AppDatabaseUpdaterProtocol = AppDatabaseUpdater.shared public var panelsUpdater: PanelsUpdaterProtocol = PanelsUpdater.shared - #if os(iOS) public var realmFatalPresentation: ((UIViewController) -> Void)? #endif diff --git a/Sources/Shared/Panels/PanelsUpdater.swift b/Sources/Shared/Panels/PanelsUpdater.swift index 67dd4259c..b14b7f83f 100644 --- a/Sources/Shared/Panels/PanelsUpdater.swift +++ b/Sources/Shared/Panels/PanelsUpdater.swift @@ -1,9 +1,10 @@ import Foundation import GRDB import PromiseKit +import UIKit public protocol PanelsUpdaterProtocol { - func update() + func update(uiApplicationState: () -> UIApplication.State) } final class PanelsUpdater: PanelsUpdaterProtocol { @@ -12,7 +13,7 @@ final class PanelsUpdater: PanelsUpdaterProtocol { private var tokens: [(promise: Promise, cancel: () -> Void)?] = [] private var lastUpdate: Date? - public func update() { + public func update(uiApplicationState: () -> UIApplication.State) { if let lastUpdate, lastUpdate.timeIntervalSinceNow > -5 { Current.Log.verbose("Skipping panels update, last update was \(lastUpdate)") return @@ -26,6 +27,8 @@ final class PanelsUpdater: PanelsUpdaterProtocol { for server in Current.servers.all { let request = Current.api(for: server)?.connection.send(.panels()) tokens.append(request) + + guard uiApplicationState() == .active else { return } request?.promise.done({ [weak self] panels in self?.saveInDatabase(panels, server: server) }).cauterize()