Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
No Bug: Safeguard CoreData operations more. (#4479)
Browse files Browse the repository at this point in the history
* No Bug: Safeguard CoreData operations more.

* No Bug: Migrate CoreDatabase items after it is initialized.
  • Loading branch information
iccub committed Nov 8, 2021
1 parent 5f36651 commit 85d3b0c
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 22 deletions.
1 change: 1 addition & 0 deletions Client/Application/Delegates/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// We have to wait until pre1.12 migration is done until we proceed with database
// initialization. This is because Database container may change. See bugs #3416, #3377.
DataController.shared.initializeOnce()
Migration.postCoreDataInitMigrations()

Preferences.General.themeNormalMode.objectWillChange
.merge(with: PrivateBrowsingManager.shared.objectWillChange)
Expand Down
42 changes: 24 additions & 18 deletions Client/Application/Migration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ class Migration {
if !Preferences.Migration.playlistV1FileSettingsLocationCompleted.value {
movePlaylistV1Items()
}

if !Preferences.Migration.removeLargeFaviconsMigrationCompleted.value {
FaviconMO.clearTooLargeFavicons()
Preferences.Migration.removeLargeFaviconsMigrationCompleted.value = true
}

// Adding Observer to enable sync types

Expand Down Expand Up @@ -143,6 +138,28 @@ class Migration {
log.error("Moving Playlist Files for \(errorPath) failed: \(error)")
}
}

static func postCoreDataInitMigrations() {
if !Preferences.Migration.removeLargeFaviconsMigrationCompleted.value {
FaviconMO.clearTooLargeFavicons()
Preferences.Migration.removeLargeFaviconsMigrationCompleted.value = true
}

if Preferences.Migration.coreDataCompleted.value { return }

// In 1.6.6 we included private tabs in CoreData (temporarely) until the user did one of the following:
// - Cleared private data
// - Exited Private Mode
// - The app was terminated (bug)
// However due to a bug, some private tabs remain in the container. Since 1.7 removes `isPrivate` from TabMO,
// we must dismiss any records that are private tabs during migration from Model7
TabMO.deleteAllPrivateTabs()

Domain.migrateShieldOverrides()
LegacyBookmarksHelper.migrateBookmarkOrders()

Preferences.Migration.coreDataCompleted.value = true
}
}

fileprivate extension Preferences {
Expand All @@ -158,6 +175,8 @@ fileprivate extension Preferences {
Option<Bool>(key: "migration.playlistv1-file-settings-location-completed", default: false)
static let removeLargeFaviconsMigrationCompleted =
Option<Bool>(key: "migration.remove-large-favicons", default: false)

static let coreDataCompleted = Option<Bool>(key: "migration.cd-completed", default: false)
}

/// Migrate the users preferences from prior versions of the app (<2.0)
Expand Down Expand Up @@ -233,19 +252,6 @@ fileprivate extension Preferences {
// This needs to be translated to our new preference.
Preferences.General.isFirstLaunch.value = Preferences.DAU.lastLaunchInfo.value == nil

// Core Data

// In 1.6.6 we included private tabs in CoreData (temporarely) until the user did one of the following:
// - Cleared private data
// - Exited Private Mode
// - The app was terminated (bug)
// However due to a bug, some private tabs remain in the container. Since 1.7 removes `isPrivate` from TabMO,
// we must dismiss any records that are private tabs during migration from Model7
TabMO.deleteAllPrivateTabs()

Domain.migrateShieldOverrides()
LegacyBookmarksHelper.migrateBookmarkOrders()

Preferences.Migration.completed.value = true
}
}
10 changes: 6 additions & 4 deletions Data/models/CRUDProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protocol Readable where Self: NSManagedObject {
}

// MARK: - Implementations
extension Deletable where Self: NSManagedObject {
extension Deletable {
func delete(context: WriteContext = .new(inMemory: false)) {

DataController.perform(context: context) { context in
Expand Down Expand Up @@ -63,8 +63,10 @@ extension Deletable where Self: NSManagedObject {

// Batch delete writes directly to the persistent store.
// Therefore contexts and in-memory objects must be updated manually.
let result = try context.execute(deleteRequest) as? NSBatchDeleteResult
guard let objectIDArray = result?.result as? [NSManagedObjectID] else { return }

guard let objectIDArray = try context.persistentStoreCoordinator?
.execute(deleteRequest, with: context) as? [NSManagedObjectID] else { return }

let changes = [NSDeletedObjectsKey: objectIDArray]

// Merging changes to view context is important because fetch results controllers
Expand All @@ -80,7 +82,7 @@ extension Deletable where Self: NSManagedObject {
}
}

extension Readable where Self: NSManagedObject {
extension Readable {
static func count(predicate: NSPredicate? = nil,
context: NSManagedObjectContext = DataController.viewContext) -> Int? {
let request = getFetchRequest()
Expand Down
4 changes: 4 additions & 0 deletions Data/models/DataController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ public class DataController {

static func perform(context: WriteContext = .new(inMemory: false), save: Bool = true,
task: @escaping (NSManagedObjectContext) -> Void) {
if !DataController.shared.initializationCompleted && !AppConstants.isRunningTest {
assertionFailure("Performing on context before database initialized")
return
}

switch context {
case .existing(let existingContext):
Expand Down

0 comments on commit 85d3b0c

Please sign in to comment.