Skip to content

Commit

Permalink
Issue #394: Database initialization restored
Browse files Browse the repository at this point in the history
  • Loading branch information
mipolansk committed Jul 18, 2024
1 parent 8153848 commit 62b4de3
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 98 deletions.
8 changes: 0 additions & 8 deletions SUPLA.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -871,8 +871,6 @@
A5D712752C3E708900A8EF52 /* CheckPinUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D712742C3E708900A8EF52 /* CheckPinUseCaseTests.swift */; };
A5D712772C3E769300A8EF52 /* SingleTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D712762C3E769300A8EF52 /* SingleTestCase.swift */; };
A5D7127A2C3E8F8500A8EF52 /* InitializationUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D712792C3E8F8500A8EF52 /* InitializationUseCaseTests.swift */; };
A5D7127C2C3E916C00A8EF52 /* DatabaseProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D7127B2C3E916C00A8EF52 /* DatabaseProxy.swift */; };
A5D7127E2C3E9D6D00A8EF52 /* DatabaseProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D7127D2C3E9D6D00A8EF52 /* DatabaseProxyMock.swift */; };
A5D712812C3EA2E300A8EF52 /* LockScreenVMTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D712802C3EA2E300A8EF52 /* LockScreenVMTests.swift */; };
A5D712852C3EA3A700A8EF52 /* SuplaAppCoordinatorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D712842C3EA3A700A8EF52 /* SuplaAppCoordinatorMock.swift */; };
A5D712882C3EB24900A8EF52 /* PinSetupVMTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D712872C3EB24900A8EF52 /* PinSetupVMTests.swift */; };
Expand Down Expand Up @@ -2257,8 +2255,6 @@
A5D712742C3E708900A8EF52 /* CheckPinUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckPinUseCaseTests.swift; sourceTree = "<group>"; };
A5D712762C3E769300A8EF52 /* SingleTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleTestCase.swift; sourceTree = "<group>"; };
A5D712792C3E8F8500A8EF52 /* InitializationUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitializationUseCaseTests.swift; sourceTree = "<group>"; };
A5D7127B2C3E916C00A8EF52 /* DatabaseProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseProxy.swift; sourceTree = "<group>"; };
A5D7127D2C3E9D6D00A8EF52 /* DatabaseProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseProxyMock.swift; sourceTree = "<group>"; };
A5D712802C3EA2E300A8EF52 /* LockScreenVMTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenVMTests.swift; sourceTree = "<group>"; };
A5D712842C3EA3A700A8EF52 /* SuplaAppCoordinatorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuplaAppCoordinatorMock.swift; sourceTree = "<group>"; };
A5D712872C3EB24900A8EF52 /* PinSetupVMTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinSetupVMTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4274,7 +4270,6 @@
A54A06622AF50E8A00C03DBC /* RequestHelperMock.swift */,
A55A8DC02BB2F46F00C540D4 /* ThreadHandlerMock.swift */,
A55A8DC22BB2F4E000C540D4 /* NotificationCenterWrapperMock.swift */,
A5D7127D2C3E9D6D00A8EF52 /* DatabaseProxyMock.swift */,
);
path = Infrastructure;
sourceTree = "<group>";
Expand Down Expand Up @@ -5354,7 +5349,6 @@
A54A064B2AF3E55700C03DBC /* SuplaSchedulers.swift */,
A55A8DA72BAC50B100C540D4 /* NotificationCenterWrapper.swift */,
A55A8DBA2BB2E30900C540D4 /* ThreadHandler.swift */,
A5D7127B2C3E916C00A8EF52 /* DatabaseProxy.swift */,
A5D712972C411B2E00A8EF52 /* BuildInfo.swift */,
);
path = Infrastructure;
Expand Down Expand Up @@ -6487,7 +6481,6 @@
A553862D29E021AE00B5CF3F /* DiContainer.swift in Sources */,
A5477DBF2AA5B40C00220B4A /* SuplaHvacMode.swift in Sources */,
A503ABC02B6BD27F008CDA1F /* ChartEntryDetails.swift in Sources */,
A5D7127C2C3E916C00A8EF52 /* DatabaseProxy.swift in Sources */,
A50B5D062BEA4DA700918D18 /* RollerShutterWindowState.swift in Sources */,
A5F5C3FC2C3698040058E255 /* PinSetupVC.swift in Sources */,
A58316FA2B64507D006113F8 /* ThermometerValueProvider.swift in Sources */,
Expand Down Expand Up @@ -7028,7 +7021,6 @@
A59AB8C32A308AF700D91F1F /* ProvideDetailTypeUseCaseTests.swift in Sources */,
A54A06692AF527DB00C03DBC /* UserStateHolderMock.swift in Sources */,
A5D7129C2C4123EF00A8EF52 /* MockReturns.swift in Sources */,
A5D7127E2C3E9D6D00A8EF52 /* DatabaseProxyMock.swift in Sources */,
A59AB8B82A307F3200D91F1F /* MainVMTests.swift in Sources */,
A58B2CB62AC197E300764388 /* ChannelBaseUseCasesMocks.swift in Sources */,
A5E9CE392C35385700509702 /* SuplaAppStateHolderMock.swift in Sources */,
Expand Down
13 changes: 9 additions & 4 deletions SUPLA/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
SALog.debug("Application did finish launching with options")

#if DEBUG
// Short-circuit starting app if running unit tests
if (ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil) {
Expand All @@ -63,12 +65,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
coordinator.start(animated: true)
}

registerForNotifications()

DispatchQueue.global(qos: .userInitiated).async {
InitializationUseCase.invoke()
CoreDataManager.shared.setup {
DispatchQueue.global(qos: .userInitiated).async {
InitializationUseCase.invoke()
}
}

registerForNotifications()
return true
}

Expand Down Expand Up @@ -120,6 +123,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
SALog.debug("Application did receive remote notification")

do {
try insertNotificationUseCase.invoke(userInfo: userInfo).subscribeSynchronous()
} catch {
Expand Down
1 change: 0 additions & 1 deletion SUPLA/Core/DI/DiContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ extension DiContainer {
register(SuplaSchedulers.self, SuplaSchedulersImpl())
register(ThreadHandler.self, ThreadHandlerImpl())
register(SuplaAppStateHolder.self, SuplaAppStateHolderImpl())
register(DatabaseProxy.self, DatabaseProxyImpl())
register(BuildInfo.self, BuildInfoImpl())

// Managers
Expand Down
29 changes: 0 additions & 29 deletions SUPLA/Core/Infrastructure/DatabaseProxy.swift

This file was deleted.

59 changes: 40 additions & 19 deletions SUPLA/CoreDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,47 +69,68 @@ class CoreDataManager: NSObject {
self.migrator = migrator
}

@objc func setup() {
@objc func setup(completion: @escaping () -> Void) {
removeOldDatabases()

ValueTransformer.setValueTransformer(
GroupTotalValueTransformer(),
forName: NSValueTransformerName("GroupTotalValueTransformer")
)

migrateStoreIfNeeded()

persistentContainer.loadPersistentStores { _, error in
guard error == nil else {
fatalError("Not able to load store \(error!)")
}
loadPersistentStore {
completion()
}
}

private func loadPersistentStore(completion: @escaping () -> Void) {
migrateStoreIfNeeded {
self.persistentContainer.loadPersistentStores { _, error in
guard error == nil else {
fatalError("Not able to load store \(error!)")
}

if (self.tryRecreateAccount) {
if (SAApp.profileManager().restoreProfileFromDefaults()) {
var settings = self.settings
settings.anyAccountRegistered = true
if (self.tryRecreateAccount) {
DispatchQueue.global(qos: .userInitiated).async {
if (SAApp.profileManager().restoreProfileFromDefaults()) {
var settings = self.settings
settings.anyAccountRegistered = true
}
DispatchQueue.main.async {
completion()
}
}
} else {
completion()
}
}
}
}

private func migrateStoreIfNeeded() {
private func migrateStoreIfNeeded(completion: @escaping () -> Void) {
guard let storeUrl = persistentContainer.persistentStoreDescriptions.first?.url else {
fatalError("persistentContainer was not set up properly")
}

if migrator.requiresMigration(at: storeUrl, toVersion: CoreDataMigrationVersion.current) {
do {
try migrator.migrateStore(at: storeUrl, toVersion: CoreDataMigrationVersion.current)
} catch {
DispatchQueue.global(qos: .userInitiated).async {
do {
try self.migrator.migrateStore(at: storeUrl, toVersion: CoreDataMigrationVersion.current)
} catch {
#if DEBUG
fatalError("Migration failed with error \(error)")
fatalError("Migration failed with error \(error)")
#else
// If migration fails in production we want to delete the database so the
// user is able to create account again
removeCurrentDatabase()
// If migration fails in production we want to delete the database so the
// user is able to create account again
self.removeCurrentDatabase()
#endif
}

DispatchQueue.main.async {
completion()
}
}
} else {
completion()
}
}

Expand Down
4 changes: 0 additions & 4 deletions SUPLA/UseCase/App/InitializationUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,10 @@ enum InitializationUseCase {
@Singleton<ProfileRepository> var profileRepository
@Singleton<SuplaAppStateHolder> var stateHolder
@Singleton<GlobalSettings> var settings
@Singleton<DatabaseProxy> var databaseProxy
@Singleton<ThreadHandler> var threadHandler

let initializationStartTime = dateProvider.currentTimestamp()

// Migrate database if needed
databaseProxy.setup()

// Check if there is an active profile
let profileFound = (try? profileRepository.getActiveProfile().subscribeSynchronous()?.isActive) ?? false

Expand Down
27 changes: 0 additions & 27 deletions SUPLATests/Mocks/Infrastructure/DatabaseProxyMock.swift

This file was deleted.

6 changes: 0 additions & 6 deletions SUPLATests/Tests/UseCase/App/InitializationUseCaseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ final class InitializationUseCaseTests: XCTestCase {
private lazy var stateHolder: SuplaAppStateHolderMock! = SuplaAppStateHolderMock()
private lazy var settings: GlobalSettingsMock! = GlobalSettingsMock()
private lazy var threadHandler: ThreadHandlerMock! = ThreadHandlerMock()
private lazy var databaseProxy: DatabaseProxyMock! = DatabaseProxyMock()

override func setUp() {
DiContainer.shared.register(type: DateProvider.self, dateProvider!)
DiContainer.shared.register(type: (any ProfileRepository).self, profileRepository!)
DiContainer.shared.register(type: SuplaAppStateHolder.self, stateHolder!)
DiContainer.shared.register(type: GlobalSettings.self, settings!)
DiContainer.shared.register(type: ThreadHandler.self, threadHandler!)
DiContainer.shared.register(type: DatabaseProxy.self, databaseProxy!)
}

override func tearDown() {
Expand All @@ -44,7 +42,6 @@ final class InitializationUseCaseTests: XCTestCase {
stateHolder = nil
settings = nil
threadHandler = nil
databaseProxy = nil
}

func test_shouldRequirePin() {
Expand All @@ -59,7 +56,6 @@ final class InitializationUseCaseTests: XCTestCase {
XCTAssertEqual(stateHolder.handleParameters, [.lock])
XCTAssertEqual(dateProvider.currentTimestampCalls, 2)
XCTAssertEqual(threadHandler.usleepParameters, [800_000])
XCTAssertEqual(databaseProxy.setupCalls, 1)
XCTAssertEqual(profileRepository.activeProfileCalls, 1)
}

Expand All @@ -75,7 +71,6 @@ final class InitializationUseCaseTests: XCTestCase {
XCTAssertEqual(stateHolder.handleParameters, [.noAccount])
XCTAssertEqual(dateProvider.currentTimestampCalls, 2)
XCTAssertEqual(threadHandler.usleepParameters, [800_000])
XCTAssertEqual(databaseProxy.setupCalls, 1)
XCTAssertEqual(profileRepository.activeProfileCalls, 1)
}

Expand All @@ -94,7 +89,6 @@ final class InitializationUseCaseTests: XCTestCase {
XCTAssertEqual(stateHolder.handleParameters, [.initialized])
XCTAssertEqual(dateProvider.currentTimestampCalls, 2)
XCTAssertEqual(threadHandler.usleepParameters, [])
XCTAssertEqual(databaseProxy.setupCalls, 1)
XCTAssertEqual(profileRepository.activeProfileCalls, 1)
}
}

0 comments on commit 62b4de3

Please sign in to comment.