Prevent sync errors from crashing the app
This commit is contained in:
parent
9deafa4b33
commit
be788bd0a6
|
@ -19,6 +19,7 @@ extension Item {
|
|||
@NSManaged public var author: String?
|
||||
@NSManaged public var content: String?
|
||||
@NSManaged public var id: String?
|
||||
@NSManaged public var needsReadStateSync: Bool
|
||||
@NSManaged public var published: Date?
|
||||
@NSManaged public var read: Bool
|
||||
@NSManaged public var title: String?
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<attribute name="author" optional="YES" attributeType="String"/>
|
||||
<attribute name="content" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" attributeType="String"/>
|
||||
<attribute name="needsReadStateSync" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="published" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="read" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="title" optional="YES" attributeType="String"/>
|
||||
|
@ -29,7 +30,7 @@
|
|||
<elements>
|
||||
<element name="Feed" positionX="-54" positionY="9" width="128" height="119"/>
|
||||
<element name="Group" positionX="-63" positionY="-18" width="128" height="74"/>
|
||||
<element name="Item" positionX="-45" positionY="63" width="128" height="149"/>
|
||||
<element name="Item" positionX="-45" positionY="63" width="128" height="164"/>
|
||||
<element name="SyncState" positionX="-63" positionY="90" width="128" height="44"/>
|
||||
</elements>
|
||||
</model>
|
|
@ -55,29 +55,59 @@ class FervorController {
|
|||
accessToken = token.accessToken
|
||||
}
|
||||
|
||||
func syncAll() async {
|
||||
func syncAll() async throws {
|
||||
logger.info("Syncing groups and feeds")
|
||||
async let groups = try! client.groups()
|
||||
async let feeds = try! client.feeds()
|
||||
try! await persistentContainer.sync(serverGroups: groups, serverFeeds: feeds)
|
||||
async let groups = try client.groups()
|
||||
async let feeds = try client.feeds()
|
||||
try await persistentContainer.sync(serverGroups: groups, serverFeeds: feeds)
|
||||
|
||||
let lastSync = try! await persistentContainer.lastSyncDate()
|
||||
let lastSync = try await persistentContainer.lastSyncDate()
|
||||
logger.info("Syncing items with last sync date: \(String(describing: lastSync), privacy: .public)")
|
||||
let update = try! await client.syncItems(lastSync: lastSync)
|
||||
try! await persistentContainer.syncItems(update)
|
||||
try! await persistentContainer.updateLastSyncDate(update.syncTimestamp)
|
||||
let update = try await client.syncItems(lastSync: lastSync)
|
||||
try await persistentContainer.syncItems(update)
|
||||
try await persistentContainer.updateLastSyncDate(update.syncTimestamp)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func syncReadToServer() async throws {
|
||||
var count = 0
|
||||
for case let item as Item in self.persistentContainer.viewContext.updatedObjects {
|
||||
count += 1
|
||||
// todo: there should be a batch update api endpoint
|
||||
for case let item as Item in persistentContainer.viewContext.updatedObjects {
|
||||
let f = item.read ? client.read(item:) : client.unread(item:)
|
||||
let _ = try await f(item.id!)
|
||||
do {
|
||||
let _ = try await f(item.id!)
|
||||
count += 1
|
||||
} catch {
|
||||
logger.error("Failed to sync read state: \(error.localizedDescription, privacy: .public)")
|
||||
item.needsReadStateSync = true
|
||||
}
|
||||
}
|
||||
|
||||
// try to sync items which failed last time
|
||||
let req = Item.fetchRequest()
|
||||
req.predicate = NSPredicate(format: "needsReadStateSync = YES")
|
||||
if let needsSync = try? persistentContainer.viewContext.fetch(req) {
|
||||
for item in needsSync {
|
||||
let f = item.read ? client.read(item:) : client.unread(item:)
|
||||
do {
|
||||
let _ = try await f(item.id!)
|
||||
count += 1
|
||||
item.needsReadStateSync = false
|
||||
} catch {
|
||||
logger.error("Failed to sync read state again: \(error.localizedDescription, privacy: .public)")
|
||||
item.needsReadStateSync = true
|
||||
// todo: this should probably fail after a certain number of attempts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Synced \(count, privacy: .public) read/unread to server")
|
||||
try self.persistentContainer.viewContext.save()
|
||||
|
||||
do {
|
||||
try persistentContainer.viewContext.save()
|
||||
} catch {
|
||||
logger.error("Failed to save view context: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import OSLog
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
|
@ -13,6 +14,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
|
||||
private(set) var fervorController: FervorController!
|
||||
|
||||
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "SceneDelegate")
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
|
@ -51,7 +54,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
|
||||
Task(priority: .userInitiated) {
|
||||
try await self.fervorController?.syncReadToServer()
|
||||
do {
|
||||
try await self.fervorController?.syncReadToServer()
|
||||
} catch {
|
||||
logger.error("Unable to sync read state to server: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +81,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
window!.rootViewController = nav
|
||||
|
||||
Task(priority: .userInitiated) {
|
||||
await self.fervorController.syncAll()
|
||||
do {
|
||||
try await self.fervorController.syncAll()
|
||||
} catch {
|
||||
logger.error("Unable to sync from server: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue