Delete last completion-based method in SyncDatabase.
This commit is contained in:
parent
c50ac0c84b
commit
4a5cb237a0
@ -67,43 +67,39 @@ class CloudKitSendStatusOperation: MainThreadOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private extension CloudKitSendStatusOperation {
|
private extension CloudKitSendStatusOperation {
|
||||||
|
|
||||||
func selectForProcessing() {
|
func selectForProcessing() {
|
||||||
database.selectForProcessing(limit: blockSize) { result in
|
|
||||||
|
|
||||||
MainActor.assumeIsolated {
|
Task { @MainActor in
|
||||||
switch result {
|
|
||||||
case .success(let syncStatuses):
|
|
||||||
|
|
||||||
@MainActor func stopProcessing() {
|
@MainActor func stopProcessing() {
|
||||||
if self.showProgress {
|
if self.showProgress {
|
||||||
self.refreshProgress?.completeTask()
|
self.refreshProgress?.completeTask()
|
||||||
}
|
|
||||||
os_log(.debug, log: self.log, "Done sending article statuses.")
|
|
||||||
self.operationDelegate?.operationDidComplete(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard syncStatuses.count > 0 else {
|
|
||||||
stopProcessing()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.processStatuses(syncStatuses) { stop in
|
|
||||||
if stop {
|
|
||||||
stopProcessing()
|
|
||||||
} else {
|
|
||||||
self.selectForProcessing()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case .failure(let databaseError):
|
|
||||||
os_log(.error, log: self.log, "Send status error: %@.", databaseError.localizedDescription)
|
|
||||||
self.operationDelegate?.cancelOperation(self)
|
|
||||||
}
|
}
|
||||||
|
os_log(.debug, log: self.log, "Done sending article statuses.")
|
||||||
|
self.operationDelegate?.operationDidComplete(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
guard let syncStatuses = try await self.database.selectForProcessing(limit: blockSize), !syncStatuses.isEmpty else {
|
||||||
|
stopProcessing()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.processStatuses(Array(syncStatuses)) { stop in
|
||||||
|
if stop {
|
||||||
|
stopProcessing()
|
||||||
|
} else {
|
||||||
|
self.selectForProcessing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
os_log(.error, log: self.log, "Send status error: %@.", error.localizedDescription)
|
||||||
|
self.operationDelegate?.cancelOperation(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor func processStatuses(_ syncStatuses: [SyncStatus], completion: @escaping (Bool) -> Void) {
|
@MainActor func processStatuses(_ syncStatuses: [SyncStatus], completion: @escaping (Bool) -> Void) {
|
||||||
guard let account = account, let articlesZone = articlesZone else {
|
guard let account = account, let articlesZone = articlesZone else {
|
||||||
completion(true)
|
completion(true)
|
||||||
|
@ -134,18 +134,21 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||||||
|
|
||||||
os_log(.debug, log: log, "Sending article statuses...")
|
os_log(.debug, log: log, "Sending article statuses...")
|
||||||
|
|
||||||
database.selectForProcessing { result in
|
Task { @MainActor in
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
let syncStatuses = (try await self.database.selectForProcessing()) ?? Set<SyncStatus>()
|
||||||
|
|
||||||
MainActor.assumeIsolated {
|
|
||||||
@MainActor func processStatuses(_ syncStatuses: [SyncStatus]) {
|
@MainActor func processStatuses(_ syncStatuses: [SyncStatus]) {
|
||||||
let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false }
|
let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false }
|
||||||
let deleteUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == true }
|
let deleteUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == true }
|
||||||
let createStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == true }
|
let createStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == true }
|
||||||
let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false }
|
let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false }
|
||||||
|
|
||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
var errorOccurred = false
|
var errorOccurred = false
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(createUnreadStatuses, apiCall: self.caller.createUnreadEntries) { result in
|
self.sendArticleStatuses(createUnreadStatuses, apiCall: self.caller.createUnreadEntries) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -153,7 +156,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(deleteUnreadStatuses, apiCall: self.caller.deleteUnreadEntries) { result in
|
self.sendArticleStatuses(deleteUnreadStatuses, apiCall: self.caller.deleteUnreadEntries) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -161,7 +164,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(createStarredStatuses, apiCall: self.caller.createStarredEntries) { result in
|
self.sendArticleStatuses(createStarredStatuses, apiCall: self.caller.createStarredEntries) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -169,7 +172,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(deleteStarredStatuses, apiCall: self.caller.deleteStarredEntries) { result in
|
self.sendArticleStatuses(deleteStarredStatuses, apiCall: self.caller.deleteStarredEntries) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -177,7 +180,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.notify(queue: DispatchQueue.main) {
|
group.notify(queue: DispatchQueue.main) {
|
||||||
os_log(.debug, log: self.log, "Done sending article statuses.")
|
os_log(.debug, log: self.log, "Done sending article statuses.")
|
||||||
if errorOccurred {
|
if errorOccurred {
|
||||||
@ -187,13 +190,11 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch result {
|
processStatuses(Array(syncStatuses))
|
||||||
case .success(let syncStatuses):
|
|
||||||
processStatuses(syncStatuses)
|
} catch {
|
||||||
case .failure(let databaseError):
|
completion(.failure(error))
|
||||||
completion(.failure(databaseError))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,19 +28,13 @@ final class FeedlySendArticleStatusesOperation: FeedlyOperation {
|
|||||||
override func run() {
|
override func run() {
|
||||||
os_log(.debug, log: log, "Sending article statuses...")
|
os_log(.debug, log: log, "Sending article statuses...")
|
||||||
|
|
||||||
database.selectForProcessing { result in
|
Task { @MainActor in
|
||||||
MainActor.assumeIsolated {
|
|
||||||
if self.isCanceled {
|
|
||||||
self.didFinish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch result {
|
do {
|
||||||
case .success(let syncStatuses):
|
let syncStatuses = (try await self.database.selectForProcessing()) ?? Set<SyncStatus>()
|
||||||
self.processStatuses(syncStatuses)
|
self.processStatuses(Array(syncStatuses))
|
||||||
case .failure:
|
} catch {
|
||||||
self.didFinish()
|
self.didFinish()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,10 +134,11 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
func sendArticleStatus(for account: Account, completion: @escaping (Result<Void, Error>) -> ()) {
|
func sendArticleStatus(for account: Account, completion: @escaping (Result<Void, Error>) -> ()) {
|
||||||
os_log(.debug, log: log, "Sending story statuses...")
|
os_log(.debug, log: log, "Sending story statuses...")
|
||||||
|
|
||||||
database.selectForProcessing { result in
|
Task { @MainActor in
|
||||||
|
|
||||||
|
do {
|
||||||
|
let syncStatuses = (try await self.database.selectForProcessing()) ?? Set<SyncStatus>()
|
||||||
|
|
||||||
MainActor.assumeIsolated {
|
|
||||||
|
|
||||||
@MainActor func processStatuses(_ syncStatuses: [SyncStatus]) {
|
@MainActor func processStatuses(_ syncStatuses: [SyncStatus]) {
|
||||||
let createUnreadStatuses = syncStatuses.filter {
|
let createUnreadStatuses = syncStatuses.filter {
|
||||||
$0.key == SyncStatus.Key.read && $0.flag == false
|
$0.key == SyncStatus.Key.read && $0.flag == false
|
||||||
@ -151,10 +152,10 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
let deleteStarredStatuses = syncStatuses.filter {
|
let deleteStarredStatuses = syncStatuses.filter {
|
||||||
$0.key == SyncStatus.Key.starred && $0.flag == false
|
$0.key == SyncStatus.Key.starred && $0.flag == false
|
||||||
}
|
}
|
||||||
|
|
||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
var errorOccurred = false
|
var errorOccurred = false
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendStoryStatuses(createUnreadStatuses, throttle: true, apiCall: self.caller.markAsUnread) { result in
|
self.sendStoryStatuses(createUnreadStatuses, throttle: true, apiCall: self.caller.markAsUnread) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -162,7 +163,7 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendStoryStatuses(deleteUnreadStatuses, throttle: false, apiCall: self.caller.markAsRead) { result in
|
self.sendStoryStatuses(deleteUnreadStatuses, throttle: false, apiCall: self.caller.markAsRead) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -170,7 +171,7 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendStoryStatuses(createStarredStatuses, throttle: true, apiCall: self.caller.star) { result in
|
self.sendStoryStatuses(createStarredStatuses, throttle: true, apiCall: self.caller.star) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -178,7 +179,7 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendStoryStatuses(deleteStarredStatuses, throttle: true, apiCall: self.caller.unstar) { result in
|
self.sendStoryStatuses(deleteStarredStatuses, throttle: true, apiCall: self.caller.unstar) { result in
|
||||||
group.leave()
|
group.leave()
|
||||||
@ -186,7 +187,7 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
errorOccurred = true
|
errorOccurred = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group.notify(queue: DispatchQueue.main) {
|
group.notify(queue: DispatchQueue.main) {
|
||||||
os_log(.debug, log: self.log, "Done sending article statuses.")
|
os_log(.debug, log: self.log, "Done sending article statuses.")
|
||||||
if errorOccurred {
|
if errorOccurred {
|
||||||
@ -196,13 +197,10 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch result {
|
processStatuses(Array(syncStatuses))
|
||||||
case .success(let syncStatuses):
|
} catch {
|
||||||
processStatuses(syncStatuses)
|
completion(.failure(error))
|
||||||
case .failure(let databaseError):
|
|
||||||
completion(.failure(databaseError))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,52 +199,53 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func sendArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
func sendArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||||
|
|
||||||
os_log(.debug, log: log, "Sending article statuses...")
|
os_log(.debug, log: log, "Sending article statuses...")
|
||||||
|
|
||||||
database.selectForProcessing { result in
|
Task { @MainActor in
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
let syncStatuses = (try await self.database.selectForProcessing()) ?? Set<SyncStatus>()
|
||||||
|
|
||||||
MainActor.assumeIsolated {
|
|
||||||
|
|
||||||
@MainActor func processStatuses(_ syncStatuses: [SyncStatus]) {
|
@MainActor func processStatuses(_ syncStatuses: [SyncStatus]) {
|
||||||
|
|
||||||
let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false }
|
let createUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == false }
|
||||||
let deleteUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == true }
|
let deleteUnreadStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.read && $0.flag == true }
|
||||||
let createStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == true }
|
let createStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == true }
|
||||||
let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false }
|
let deleteStarredStatuses = syncStatuses.filter { $0.key == SyncStatus.Key.starred && $0.flag == false }
|
||||||
|
|
||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(createUnreadStatuses, apiCall: self.caller.createUnreadEntries) {
|
self.sendArticleStatuses(createUnreadStatuses, apiCall: self.caller.createUnreadEntries) {
|
||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(deleteUnreadStatuses, apiCall: self.caller.deleteUnreadEntries) {
|
self.sendArticleStatuses(deleteUnreadStatuses, apiCall: self.caller.deleteUnreadEntries) {
|
||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(createStarredStatuses, apiCall: self.caller.createStarredEntries) {
|
self.sendArticleStatuses(createStarredStatuses, apiCall: self.caller.createStarredEntries) {
|
||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
self.sendArticleStatuses(deleteStarredStatuses, apiCall: self.caller.deleteStarredEntries) {
|
self.sendArticleStatuses(deleteStarredStatuses, apiCall: self.caller.deleteStarredEntries) {
|
||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
group.notify(queue: DispatchQueue.main) {
|
group.notify(queue: DispatchQueue.main) {
|
||||||
os_log(.debug, log: self.log, "Done sending article statuses.")
|
os_log(.debug, log: self.log, "Done sending article statuses.")
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch result {
|
processStatuses(Array(syncStatuses))
|
||||||
case .success(let syncStatuses):
|
} catch {
|
||||||
processStatuses(syncStatuses)
|
completion(.failure(error))
|
||||||
case .failure(let databaseError):
|
|
||||||
completion(.failure(databaseError))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,34 +110,6 @@ public actor SyncDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Compatibility
|
|
||||||
|
|
||||||
// Use the below until switching to the async version of the API.
|
|
||||||
|
|
||||||
public typealias SyncStatusesResult = Result<Array<SyncStatus>, DatabaseError>
|
|
||||||
public typealias SyncStatusesCompletionBlock = @Sendable (SyncStatusesResult) -> Void
|
|
||||||
|
|
||||||
public typealias SyncStatusArticleIDsResult = Result<Set<String>, DatabaseError>
|
|
||||||
public typealias SyncStatusArticleIDsCompletionBlock = @Sendable (SyncStatusArticleIDsResult) -> Void
|
|
||||||
|
|
||||||
public extension SyncDatabase {
|
|
||||||
|
|
||||||
nonisolated func selectForProcessing(limit: Int? = nil, completion: @escaping SyncStatusesCompletionBlock) {
|
|
||||||
|
|
||||||
Task { @MainActor in
|
|
||||||
do {
|
|
||||||
if let syncStatuses = try await self.selectForProcessing(limit: limit) {
|
|
||||||
completion(.success(Array(syncStatuses)))
|
|
||||||
} else {
|
|
||||||
completion(.success([SyncStatus]()))
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
completion(.failure(DatabaseError.suspended))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension SyncDatabase {
|
private extension SyncDatabase {
|
||||||
|
|
||||||
static let creationStatements = """
|
static let creationStatements = """
|
||||||
|
Loading…
x
Reference in New Issue
Block a user