63 lines
2.3 KiB
Swift
63 lines
2.3 KiB
Swift
import CoreData
|
|
import Foundation
|
|
import Models
|
|
import SwiftGraphQL
|
|
|
|
extension DataService {
|
|
public func fetchLinkedItemsBackgroundTask() async throws -> Int {
|
|
var fetchedItemCount = 0
|
|
|
|
// Query the server for item IDs and compare against CoreData
|
|
// to see what we're missing
|
|
let missingItemIds = try await fetchMissingItemIDs()
|
|
guard !missingItemIds.isEmpty else { return 0 }
|
|
|
|
let username: String? = await backgroundContext.perform(schedule: .immediate) {
|
|
let fetchRequest: NSFetchRequest<Models.Viewer> = Viewer.fetchRequest()
|
|
fetchRequest.fetchLimit = 1 // we should only have one viewer saved
|
|
return try? self.backgroundContext.fetch(fetchRequest).first?.username
|
|
}
|
|
|
|
guard let username = username else {
|
|
throw BasicError.message(messageText: "could not retrieve username from core data")
|
|
}
|
|
|
|
// Fetch the items
|
|
for itemID in missingItemIds { // TOOD: run these in parallel
|
|
logger.debug("fetching item with ID: \(itemID)")
|
|
_ = try await loadArticleContent(username: username, itemID: itemID, useCache: false)
|
|
fetchedItemCount += 1
|
|
logger.debug("done fetching item with ID: \(itemID)")
|
|
}
|
|
|
|
return fetchedItemCount
|
|
}
|
|
|
|
func fetchMissingItemIDs(previouslyFetchedIDs: [String] = [], cursor: String? = nil) async throws -> [String] {
|
|
logger.debug("fetching more IDS: \(cursor ?? "no cursor")")
|
|
let maxItemCount = 30
|
|
let fetchResult = try await fetchLinkedItemIDs(limit: 10, cursor: cursor)
|
|
let newItemsToFetch = await itemsNotInStore(from: fetchResult.itemIDs)
|
|
let itemsToFetch = previouslyFetchedIDs + newItemsToFetch
|
|
|
|
if newItemsToFetch.isEmpty || itemsToFetch.count > maxItemCount || fetchResult.cursor == nil {
|
|
return itemsToFetch
|
|
} else {
|
|
return try await fetchMissingItemIDs(previouslyFetchedIDs: itemsToFetch, cursor: fetchResult.cursor)
|
|
}
|
|
}
|
|
|
|
func itemsNotInStore(from itemIDs: [String]) async -> [String] {
|
|
let fetchRequest: NSFetchRequest<Models.LinkedItem> = LinkedItem.fetchRequest()
|
|
fetchRequest.predicate = NSPredicate(format: "id IN %@", itemIDs)
|
|
|
|
return await backgroundContext.perform(schedule: .immediate) {
|
|
if let foundIDs = (try? self.backgroundContext.fetch(fetchRequest).map(\.unwrappedID)) {
|
|
return itemIDs.filter { !foundIDs.contains($0) }
|
|
} else {
|
|
return []
|
|
}
|
|
}
|
|
}
|
|
}
|