Perform slow metadata to FileProviderItem conversion concurrently in FileProviderEnumerator

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
This commit is contained in:
Claudio Cambra 2023-03-18 21:35:12 +01:00
parent 808f976ae9
commit fe7ca12d9c
No known key found for this signature in database
GPG key ID: C839200C384636B0

View file

@ -273,25 +273,36 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
// MARK: - Helper methods // MARK: - Helper methods
private static func metadatasToFileProviderItems(_ itemMetadatas: [NextcloudItemMetadataTable], ncKit: NextcloudKit) -> [NSFileProviderItem] { private static func metadatasToFileProviderItems(_ itemMetadatas: [NextcloudItemMetadataTable], ncKit: NextcloudKit, completionHandler: @escaping(_ items: [NSFileProviderItem]) -> Void) {
var items: [NSFileProviderItem] = [] var items: [NSFileProviderItem] = []
let dispatchGroup = DispatchGroup()
for itemMetadata in itemMetadatas { for itemMetadata in itemMetadatas {
dispatchGroup.enter()
DispatchQueue.global(qos: .userInitiated).async {
if itemMetadata.e2eEncrypted { if itemMetadata.e2eEncrypted {
Logger.enumeration.info("Skipping encrypted metadata in enumeration: \(itemMetadata.ocId) \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash))") Logger.enumeration.info("Skipping encrypted metadata in enumeration: \(itemMetadata.ocId, privacy: .public) \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash))")
continue dispatchGroup.leave()
return
} }
if let parentItemIdentifier = NextcloudFilesDatabaseManager.shared.parentItemIdentifierFromMetadata(itemMetadata) { if let parentItemIdentifier = NextcloudFilesDatabaseManager.shared.parentItemIdentifierFromMetadata(itemMetadata) {
let item = FileProviderItem(metadata: itemMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit) let item = FileProviderItem(metadata: itemMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit)
Logger.enumeration.debug("Will enumerate item with ocId: \(itemMetadata.ocId) and name: \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash))") Logger.enumeration.debug("Will enumerate item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash))")
items.append(item) items.append(item)
} else { } else {
Logger.enumeration.error("Could not get valid parentItemIdentifier for item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash)), skipping enumeration") Logger.enumeration.error("Could not get valid parentItemIdentifier for item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash)), skipping enumeration")
} }
dispatchGroup.leave()
}
} }
return items dispatchGroup.notify(queue: DispatchQueue.main) {
completionHandler(items)
}
} }
private static func fileProviderPageforNumPage(_ numPage: Int) -> NSFileProviderPage { private static func fileProviderPageforNumPage(_ numPage: Int) -> NSFileProviderPage {
@ -300,7 +311,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
private static func completeEnumerationObserver(_ observer: NSFileProviderEnumerationObserver, ncKit: NextcloudKit, numPage: Int, itemMetadatas: [NextcloudItemMetadataTable]) { private static func completeEnumerationObserver(_ observer: NSFileProviderEnumerationObserver, ncKit: NextcloudKit, numPage: Int, itemMetadatas: [NextcloudItemMetadataTable]) {
let items = FileProviderEnumerator.metadatasToFileProviderItems(itemMetadatas, ncKit: ncKit) metadatasToFileProviderItems(itemMetadatas, ncKit: ncKit) { items in
observer.didEnumerate(items) observer.didEnumerate(items)
Logger.enumeration.info("Did enumerate \(items.count) items") Logger.enumeration.info("Did enumerate \(items.count) items")
@ -316,6 +327,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
*/ */
observer.finishEnumerating(upTo: fileProviderPageforNumPage(numPage)) observer.finishEnumerating(upTo: fileProviderPageforNumPage(numPage))
} }
}
private static func completeChangesObserver(_ observer: NSFileProviderChangeObserver, anchor: NSFileProviderSyncAnchor, ncKit: NextcloudKit, newMetadatas: [NextcloudItemMetadataTable]?, updatedMetadatas: [NextcloudItemMetadataTable]?, deletedMetadatas: [NextcloudItemMetadataTable]?) { private static func completeChangesObserver(_ observer: NSFileProviderChangeObserver, anchor: NSFileProviderSyncAnchor, ncKit: NextcloudKit, newMetadatas: [NextcloudItemMetadataTable]?, updatedMetadatas: [NextcloudItemMetadataTable]?, deletedMetadatas: [NextcloudItemMetadataTable]?) {
@ -341,36 +353,19 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
allDeletedMetadatas = deletedMetadatas allDeletedMetadatas = deletedMetadatas
} }
var allFpItemUpdates: [FileProviderItem] = []
var allFpItemDeletionsIdentifiers = Array(allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) }) var allFpItemDeletionsIdentifiers = Array(allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) })
for updMetadata in allUpdatedMetadatas {
guard let parentItemIdentifier = NextcloudFilesDatabaseManager.shared.parentItemIdentifierFromMetadata(updMetadata) else {
Logger.enumeration.warning("Not enumerating change for metadata: \(updMetadata.ocId) \(updMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash)) as could not get parent item metadata.")
continue
}
guard !updMetadata.e2eEncrypted else {
// Precaution, if all goes well in NKFile conversion then this should not happen
// TODO: Remove when E2EE supported
Logger.enumeration.info("Encrypted metadata in changes enumeration \(updMetadata.ocId) \(updMetadata.fileName, privacy: OSLogPrivacy.auto(mask: .hash)), adding to deletions")
allFpItemDeletionsIdentifiers.append(NSFileProviderItemIdentifier(updMetadata.ocId))
continue
}
let fpItem = FileProviderItem(metadata: updMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit)
allFpItemUpdates.append(fpItem)
}
if !allFpItemUpdates.isEmpty {
observer.didUpdate(allFpItemUpdates)
}
if !allFpItemDeletionsIdentifiers.isEmpty { if !allFpItemDeletionsIdentifiers.isEmpty {
observer.didDeleteItems(withIdentifiers: allFpItemDeletionsIdentifiers) observer.didDeleteItems(withIdentifiers: allFpItemDeletionsIdentifiers)
} }
Logger.enumeration.info("Processed \(allUpdatedMetadatas.count) new or updated metadatas, \(allDeletedMetadatas.count) deleted metadatas.") metadatasToFileProviderItems(allUpdatedMetadatas, ncKit: ncKit) { updatedItems in
if !updatedItems.isEmpty {
observer.didUpdate(updatedItems)
}
Logger.enumeration.info("Processed \(updatedItems.count) new or updated metadatas, \(allDeletedMetadatas.count) deleted metadatas.")
observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) observer.finishEnumeratingChanges(upTo: anchor, moreComing: false)
} }
}
} }