create offline sync function

This commit is contained in:
Satindar Dhillon 2022-04-25 22:02:36 -07:00
parent 8433f3a226
commit 791719ac05
4 changed files with 91 additions and 4 deletions

View file

@ -2,9 +2,7 @@ import CoreData
import Foundation
public extension Highlight {
var unwrappedID: String {
id ?? ""
}
var unwrappedID: String { id ?? "" }
static func lookup(byID highlightID: String, inContext context: NSManagedObjectContext) -> Highlight? {
let fetchRequest: NSFetchRequest<Models.Highlight> = Highlight.fetchRequest()

View file

@ -1,6 +1,10 @@
import Foundation
import Models
public enum CoreDataError: Error {
case general
}
public enum ServerError: String, Error {
case noConnection
case unauthenticated

View file

@ -4,7 +4,7 @@ import Models
import SwiftGraphQL
extension DataService {
// swiftlint:disable:next function_parameter_count function_body_length
// swiftlint:disable:next function_parameter_count
public func mergeHighlights(
shortId: String,
highlightID: String,

View file

@ -0,0 +1,85 @@
import CoreData
import Foundation
import Models
extension DataService {
func syncOfflineItemsWithServerIfNeeded() async throws {
// TODO: send a simple request to see if we're online?
var unsyncedLinkedItems = [LinkedItem]()
var unsyncedHighlights = [Highlight]()
// LinkedItems
let itemsFetchRequest: NSFetchRequest<Models.LinkedItem> = LinkedItem.fetchRequest()
itemsFetchRequest.predicate = NSPredicate(
format: "serverSyncStatus != %@", ServerSyncStatus.isNSync.rawValue
)
// Highlights
let highlightsFetchRequest: NSFetchRequest<Models.Highlight> = Highlight.fetchRequest()
highlightsFetchRequest.predicate = NSPredicate(
format: "serverSyncStatus != %@", ServerSyncStatus.isNSync.rawValue
)
try await backgroundContext.perform(schedule: .immediate) { [weak self] in
guard let self = self else { return }
do {
unsyncedLinkedItems = try itemsFetchRequest.execute()
unsyncedHighlights = try highlightsFetchRequest.execute()
} catch {
throw CoreDataError.general
}
self.syncLinkedItems(unsyncedLinkedItems: unsyncedLinkedItems)
self.syncHighlights(unsyncedHighlights: unsyncedHighlights)
}
}
private func syncLinkedItems(unsyncedLinkedItems: [LinkedItem]) {
for item in unsyncedLinkedItems {
guard let syncStatus = ServerSyncStatus(rawValue: Int(item.serverSyncStatus)) else { continue }
switch syncStatus {
case .isNSync, .isSyncing, .needsCreation:
break
case .needsDeletion:
item.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
syncLinkDeletion(itemID: item.unwrappedID, objectID: item.objectID)
case .needsUpdate:
item.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
syncLinkArchiveStatus(itemID: item.unwrappedID, objectID: item.objectID, archived: item.isArchived)
}
}
}
private func syncHighlights(unsyncedHighlights: [Highlight]) {
for highlight in unsyncedHighlights {
guard let syncStatus = ServerSyncStatus(rawValue: Int(highlight.serverSyncStatus)) else { continue }
switch syncStatus {
case .isNSync, .isSyncing:
break
case .needsCreation:
highlight.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
syncHighlightCreation(
highlight: InternalHighlight.make(from: highlight),
articleId: highlight.linkedItem?.unwrappedID ?? ""
)
case .needsDeletion:
highlight.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
syncHighlightDeletion(highlightID: highlight.unwrappedID, objectID: highlight.objectID)
case .needsUpdate:
if let annotation = highlight.annotation {
highlight.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
syncHighlightAttributes(
highlightID: highlight.unwrappedID,
objectID: highlight.objectID,
annotation: annotation
)
} else {
highlight.serverSyncStatus = Int64(ServerSyncStatus.isNSync.rawValue)
}
}
}
}
}