CoreStore icon indicating copy to clipboard operation
CoreStore copied to clipboard

adding support of persistent history tracking

Open dlavlinskyi opened this issue 7 years ago • 10 comments

Apple added NSPersistentContainer which makes setup of CoreData much easier, same as part of CoreStore does. CoreStore is really cool CD wrapper, I would love to use it in my project, except one "but":

I'm trying to use NSPersistentHistory classes to fetch changes from persistent store, to do so i have to add set true to NSPersistentHistoryTrackingKey key for store options. Apple provided following API:

let description: NSPersistentStoreDescription = ... // Your default configuration here
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)

let container = ... // Your default configuration here
container.persistentStoreDescriptions = [description]

than to fetch history:

let historyFetchRequest = NSPersistentHistoryChangeRequest.fetchHistory(after: timestamp)
let context = CoreStore.defaultStack.unsafeContext()
do {
      let result = try context.execute(historyFetchRequest) as? NSPersistentHistoryResult
      let transactions = result?.result as! [NSPersistentHistoryTransaction]
      print(transactions)
} catch {
      print(error)
}

I tried to add this option using CoreStore in SQLiteSore class:

public let storeOptions: [AnyHashable: Any]? = autoreleasepool {
        
        var storeOptions: [AnyHashable: Any] = [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
        if #available(iOS 11.0, macOS 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) {

            storeOptions[NSBinaryStoreInsecureDecodingCompatibilityOption] = true
            storeOptions[NSPersistentHistoryTrackingKey] = true
        }
        return storeOptions
    }

but history fetch request fails with "very informative" error nilError. So, I suppose persistent history tracking works only when persistent stores was initialized by NSPersistentContainer. Do you have any other ideas or any suggestions how to solve this issue? Am I doing something wrong? One of my ideas was to make abstraction of DataStack (instead of class DataStack use protocol DataStack). Protocol will have all properties required by Transactions and Quering extensions. Will it be good idea to start with? Won't it cause a break of main architecture ideas?

dlavlinskyi avatar Dec 26 '18 16:12 dlavlinskyi

I had the same issue (though unrelated to CoreStore). Turns out that in order to be able to fetch persistent history transactions, NSManagedObjectContext must be created using NSPersistentContainer API.

andris-zalitis avatar Feb 08 '19 18:02 andris-zalitis

I have plans to support this, but I've only just begun prototyping for stores that support persistent history tracking, with "shared stores" as the main use-case for sharing data between multiple apps and extensions. I've heard mentions about it requiring NSPersistentContainer, but I personally believe it should be doable with manually managed NSPersistentStoreCoordinator, we'd just have to find the right parameters for the setup. If it's needed, CoreStore might need to migrate to using NSPersistentContainer, which is another big refactor in itself.

That said, I cannot promise a release date and it may be a long time before we'd have a working branch for it.

JohnEstropia avatar Sep 30 '21 01:09 JohnEstropia

Hi @JohnEstropia, any updates on this?

spacedema avatar Jan 20 '22 15:01 spacedema

I'm still in the experimental stages for this since I don't have a project that urgently needs it right now. I do have the interface in place already for shared stores using App Group Identifiers, but the internal implementation is still in progress.

JohnEstropia avatar Jan 21 '22 08:01 JohnEstropia

Ok, thanks for the answer https://github.com/JohnEstropia/CoreStore/issues/440 it will be possible to implement showcase app data in Spotlight https://developer.apple.com/videos/play/wwdc2021/10098/ and Access Attributes of a Deleted Object https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes

There is a problem with 1->M relationship and cascade delete in ListMonotor, when deleting the root object, nested records that are deleted cascaded have all fields null ("" or 0) in ListMonitor

I think Implementing Persistent History Tracking will solve many problems and be useful to many Core Store users.

spacedema avatar Jan 21 '22 08:01 spacedema

Yes, history tracking will enable app extensions (such as the Spotlight Import extension) to share Core Data records with the main app.

I'm not sure the ListMonitor issue(?) you mentioned is related though. Does your relationship have correct delete rules on both Entities of the relationship?

JohnEstropia avatar Jan 21 '22 09:01 JohnEstropia

The method described in https://github.com/JohnEstropia/CoreStore/issues/362 solves the problem of deleting Attachments entities, but if I delete the Root object, which will cascade delete Attachments, in Attachments ListMonitor listMonitorWillChange, all fields will be null("" or 0). Therefore, I thought that Access Attributes of a Deleted Object could solve this problem. And yes, relationship has correct delete rules on both Entities of the relationship (Cascade for Root entity attachments collection and Nullify for Attachments entity)

spacedema avatar Jan 21 '22 09:01 spacedema

Should I create a separate issue for this case, @JohnEstropia ?

spacedema avatar Jan 21 '22 10:01 spacedema

Yes, thanks @spacedema! Please include relevant code for the affected Entities

JohnEstropia avatar Jan 21 '22 10:01 JohnEstropia

@JohnEstropia https://github.com/JohnEstropia/CoreStore/issues/447

spacedema avatar Jan 21 '22 10:01 spacedema