Move remote change processing to separate context to avoid blocking background context
This commit is contained in:
parent
4dbc4ebeb2
commit
bff7585fa9
|
@ -31,18 +31,21 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
||||||
context.persistentStoreCoordinator = self.persistentStoreCoordinator
|
context.persistentStoreCoordinator = self.persistentStoreCoordinator
|
||||||
context.automaticallyMergesChangesFromParent = true
|
context.automaticallyMergesChangesFromParent = true
|
||||||
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||||
|
context.name = "Background"
|
||||||
return context
|
return context
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private(set) lazy var prefetchBackgroundContext: NSManagedObjectContext = {
|
// remote change processing happens on its own context, since it can sometimes take
|
||||||
|
// a really long time (upwards of a minute) and shouldn't block other things using the background context
|
||||||
|
private lazy var remoteChangesBackgroundContext: NSManagedObjectContext = {
|
||||||
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||||
context.persistentStoreCoordinator = self.persistentStoreCoordinator
|
context.persistentStoreCoordinator = self.persistentStoreCoordinator
|
||||||
context.automaticallyMergesChangesFromParent = true
|
context.automaticallyMergesChangesFromParent = true
|
||||||
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||||
|
context.name = "RemoteChanges"
|
||||||
return context
|
return context
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var remoteChangeHandlerQueue = DispatchQueue(label: "PersistentStore remote changes")
|
|
||||||
private var lastRemoteChangeToken: NSPersistentHistoryToken?
|
private var lastRemoteChangeToken: NSPersistentHistoryToken?
|
||||||
|
|
||||||
// TODO: consider sending managed objects through this to avoid re-fetching things unnecessarily
|
// TODO: consider sending managed objects through this to avoid re-fetching things unnecessarily
|
||||||
|
@ -182,6 +185,7 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
||||||
|
|
||||||
viewContext.automaticallyMergesChangesFromParent = true
|
viewContext.automaticallyMergesChangesFromParent = true
|
||||||
viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||||
|
viewContext.name = "View"
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(managedObjectsDidChange), name: .NSManagedObjectContextObjectsDidChange, object: viewContext)
|
NotificationCenter.default.addObserver(self, selector: #selector(managedObjectsDidChange), name: .NSManagedObjectContextObjectsDidChange, object: viewContext)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(remoteChanges), name: .NSPersistentStoreRemoteChange, object: persistentStoreCoordinator)
|
NotificationCenter.default.addObserver(self, selector: #selector(remoteChanges), name: .NSPersistentStoreRemoteChange, object: persistentStoreCoordinator)
|
||||||
|
@ -509,13 +513,12 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
||||||
guard let token = notification.userInfo?[NSPersistentHistoryTokenKey] as? NSPersistentHistoryToken else {
|
guard let token = notification.userInfo?[NSPersistentHistoryTokenKey] as? NSPersistentHistoryToken else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remoteChangeHandlerQueue.async {
|
remoteChangesBackgroundContext.perform {
|
||||||
defer {
|
defer {
|
||||||
self.lastRemoteChangeToken = token
|
self.lastRemoteChangeToken = token
|
||||||
}
|
}
|
||||||
let req = NSPersistentHistoryChangeRequest.fetchHistory(after: self.lastRemoteChangeToken)
|
let req = NSPersistentHistoryChangeRequest.fetchHistory(after: self.lastRemoteChangeToken)
|
||||||
self.backgroundContext.performAndWait {
|
if let result = try? self.remoteChangesBackgroundContext.execute(req) as? NSPersistentHistoryResult,
|
||||||
if let result = try? self.backgroundContext.execute(req) as? NSPersistentHistoryResult,
|
|
||||||
let transactions = result.result as? [NSPersistentHistoryTransaction],
|
let transactions = result.result as? [NSPersistentHistoryTransaction],
|
||||||
!transactions.isEmpty {
|
!transactions.isEmpty {
|
||||||
var changedHashtags = false
|
var changedHashtags = false
|
||||||
|
@ -557,7 +560,6 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue