Use batch update endpoint for marking items (un)read
This commit is contained in:
parent
c41a81414d
commit
a6d29b203c
|
@ -131,6 +131,20 @@ public class FervorClient {
|
|||
return try await performRequest(request)
|
||||
}
|
||||
|
||||
public func read(ids: [FervorID]) async throws -> [FervorID] {
|
||||
var request = URLRequest(url: buildURL(path: "/api/v1/items/read"))
|
||||
request.httpMethod = "POST"
|
||||
request.setURLEncodedBody(params: ["ids": ids.joined(separator: ",")])
|
||||
return try await performRequest(request)
|
||||
}
|
||||
|
||||
public func unread(ids: [FervorID]) async throws -> [FervorID] {
|
||||
var request = URLRequest(url: buildURL(path: "/api/v1/items/unread"))
|
||||
request.httpMethod = "POST"
|
||||
request.setURLEncodedBody(params: ["ids": ids.joined(separator: ",")])
|
||||
return try await performRequest(request)
|
||||
}
|
||||
|
||||
public struct Auth {
|
||||
public let accessToken: String
|
||||
public let refreshToken: String?
|
||||
|
|
|
@ -87,36 +87,38 @@ class FervorController {
|
|||
}
|
||||
|
||||
@MainActor
|
||||
func syncReadToServer() async throws {
|
||||
func syncReadToServer() async {
|
||||
var count = 0
|
||||
// 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:)
|
||||
do {
|
||||
let _ = try await f(item.id!)
|
||||
count += 1
|
||||
} catch {
|
||||
logger.error("Failed to sync read state: \(String(describing: error), 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:)
|
||||
if var needsSync = try? persistentContainer.viewContext.fetch(req) {
|
||||
let firstReadIndex = needsSync.partition(by: \.read)
|
||||
let unreadIDs = needsSync[..<firstReadIndex].map(\.id.unsafelyUnwrapped)
|
||||
let readIDs = needsSync[firstReadIndex...].map(\.id.unsafelyUnwrapped)
|
||||
var updatedIDs = Set<FervorID>()
|
||||
if !unreadIDs.isEmpty {
|
||||
do {
|
||||
let _ = try await f(item.id!)
|
||||
count += 1
|
||||
item.needsReadStateSync = false
|
||||
let ids = try await client.unread(ids: unreadIDs)
|
||||
updatedIDs.formUnion(ids)
|
||||
} catch {
|
||||
logger.error("Failed to sync read state again: \(String(describing: error), privacy: .public)")
|
||||
item.needsReadStateSync = true
|
||||
// todo: this should probably fail after a certain number of attempts
|
||||
logger.error("Failed to sync unread state: \(String(describing: error), privacy: .public)")
|
||||
}
|
||||
}
|
||||
if !readIDs.isEmpty {
|
||||
do {
|
||||
let ids = try await client.read(ids: readIDs)
|
||||
updatedIDs.formUnion(ids)
|
||||
} catch {
|
||||
logger.error("Failed to sync read state: \(String(describing: error), privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
||||
count += updatedIDs.count
|
||||
for item in needsSync where updatedIDs.contains(item.id!) {
|
||||
item.needsReadStateSync = false
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Synced \(count, privacy: .public) read/unread to server")
|
||||
|
|
|
@ -81,11 +81,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
|
||||
if let fervorController = fervorController {
|
||||
Task(priority: .userInitiated) {
|
||||
do {
|
||||
try await fervorController.syncReadToServer()
|
||||
} catch {
|
||||
logger.error("Unable to sync read state to server: \(String(describing: error), privacy: .public)")
|
||||
}
|
||||
await fervorController.syncReadToServer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue