diff --git a/Frameworks/SyncDatabase/SyncDatabase.swift b/Frameworks/SyncDatabase/SyncDatabase.swift index f7d69a8a6..baa95f0ee 100644 --- a/Frameworks/SyncDatabase/SyncDatabase.swift +++ b/Frameworks/SyncDatabase/SyncDatabase.swift @@ -26,23 +26,23 @@ public struct SyncDatabase { // MARK: - API - public func insertStatuses(_ statuses: [SyncStatus], completion: VoidCompletionBlock? = nil) { + public func insertStatuses(_ statuses: [SyncStatus], completion: DatabaseCompletionBlock? = nil) { syncStatusTable.insertStatuses(statuses, completion: completion) } - public func selectForProcessing() -> [SyncStatus] { - return syncStatusTable.selectForProcessing() + public func selectForProcessing() throws -> [SyncStatus] { + return try syncStatusTable.selectForProcessing() } - public func selectPendingCount() -> Int { - return syncStatusTable.selectPendingCount() + public func selectPendingCount() throws -> Int { + return try syncStatusTable.selectPendingCount() } - public func resetSelectedForProcessing(_ articleIDs: [String], completion: VoidCompletionBlock? = nil) { + public func resetSelectedForProcessing(_ articleIDs: [String], completion: DatabaseCompletionBlock? = nil) { syncStatusTable.resetSelectedForProcessing(articleIDs, completion: completion) } - public func deleteSelectedForProcessing(_ articleIDs: [String], completion: VoidCompletionBlock? = nil) { + public func deleteSelectedForProcessing(_ articleIDs: [String], completion: DatabaseCompletionBlock? = nil) { syncStatusTable.deleteSelectedForProcessing(articleIDs, completion: completion) } diff --git a/Frameworks/SyncDatabase/SyncStatusTable.swift b/Frameworks/SyncDatabase/SyncStatusTable.swift index 030bb54f1..0d5dc8041 100644 --- a/Frameworks/SyncDatabase/SyncStatusTable.swift +++ b/Frameworks/SyncDatabase/SyncStatusTable.swift @@ -20,92 +20,118 @@ struct SyncStatusTable: DatabaseTable { self.queue = queue } - func selectForProcessing() -> [SyncStatus] { + func selectForProcessing() throws -> [SyncStatus] { var statuses: Set? = nil - - guard !queue.isSuspended else { - return [SyncStatus]() - } - - queue.runInDatabaseSync { database in - let updateSQL = "update syncStatus set selected = true" - database.executeUpdate(updateSQL, withArgumentsIn: nil) - - let selectSQL = "select * from syncStatus where selected == true" - if let resultSet = database.executeQuery(selectSQL, withArgumentsIn: nil) { - statuses = resultSet.mapToSet(self.statusWithRow) + var error: DatabaseError? + + queue.runInTransactionSync { databaseResult in + + func makeDatabaseCall(_ database: FMDatabase) { + let updateSQL = "update syncStatus set selected = true" + database.executeUpdate(updateSQL, withArgumentsIn: nil) + + let selectSQL = "select * from syncStatus where selected == true" + if let resultSet = database.executeQuery(selectSQL, withArgumentsIn: nil) { + statuses = resultSet.mapToSet(self.statusWithRow) + } + } + + switch databaseResult { + case .success(let database): + makeDatabaseCall(database) + case .failure(let databaseError): + error = databaseError } } + if let error = error { + throw(error) + } return statuses != nil ? Array(statuses!) : [SyncStatus]() } - func selectPendingCount() -> Int { + func selectPendingCount() throws -> Int { var count: Int = 0 - - guard !queue.isSuspended else { - return count - } - - queue.runInDatabaseSync { database in - let sql = "select count(*) from syncStatus" - if let resultSet = database.executeQuery(sql, withArgumentsIn: nil) { - count = numberWithCountResultSet(resultSet) + var error: DatabaseError? + + queue.runInDatabaseSync { databaseResult in + + func makeDatabaseCall(_ database: FMDatabase) { + let sql = "select count(*) from syncStatus" + if let resultSet = database.executeQuery(sql, withArgumentsIn: nil) { + count = numberWithCountResultSet(resultSet) + } + } + + switch databaseResult { + case .success(let database): + makeDatabaseCall(database) + case .failure(let databaseError): + error = databaseError } } - + + if let error = error { + throw(error) + } return count } - - func resetSelectedForProcessing(_ articleIDs: [String], completion: VoidCompletionBlock? = nil) { - guard !queue.isSuspended else { - if let completion = completion { - callVoidCompletionBlock(completion) - } - return - } - queue.runInTransaction { database in - let parameters = articleIDs.map { $0 as AnyObject } - let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(articleIDs.count))! - let updateSQL = "update syncStatus set selected = false where articleID in \(placeholders)" - database.executeUpdate(updateSQL, withArgumentsIn: parameters) - if let completion = completion { - callVoidCompletionBlock(completion) - } + + func resetSelectedForProcessing(_ articleIDs: [String], completion: DatabaseCompletionBlock? = nil) { + queue.runInTransaction { databaseResult in + + func makeDatabaseCall(_ database: FMDatabase) { + let parameters = articleIDs.map { $0 as AnyObject } + let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(articleIDs.count))! + let updateSQL = "update syncStatus set selected = false where articleID in \(placeholders)" + database.executeUpdate(updateSQL, withArgumentsIn: parameters) + } + + switch databaseResult { + case .success(let database): + makeDatabaseCall(database) + callCompletion(completion, nil) + case .failure(let databaseError): + callCompletion(completion, databaseError) + } } } - func deleteSelectedForProcessing(_ articleIDs: [String], completion: VoidCompletionBlock? = nil) { - guard !queue.isSuspended else { - if let completion = completion { - callVoidCompletionBlock(completion) - } - return - } - queue.runInTransaction { database in - let parameters = articleIDs.map { $0 as AnyObject } - let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(articleIDs.count))! - let deleteSQL = "delete from syncStatus where articleID in \(placeholders)" - database.executeUpdate(deleteSQL, withArgumentsIn: parameters) - if let completion = completion { - callVoidCompletionBlock(completion) - } + func deleteSelectedForProcessing(_ articleIDs: [String], completion: DatabaseCompletionBlock? = nil) { + queue.runInTransaction { databaseResult in + + func makeDatabaseCall(_ database: FMDatabase) { + let parameters = articleIDs.map { $0 as AnyObject } + let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(articleIDs.count))! + let deleteSQL = "delete from syncStatus where articleID in \(placeholders)" + database.executeUpdate(deleteSQL, withArgumentsIn: parameters) + } + + switch databaseResult { + case .success(let database): + makeDatabaseCall(database) + callCompletion(completion, nil) + case .failure(let databaseError): + callCompletion(completion, databaseError) + } } } - func insertStatuses(_ statuses: [SyncStatus], completion: VoidCompletionBlock? = nil) { - guard !queue.isSuspended else { - if let completion = completion { - callVoidCompletionBlock(completion) - } - return - } - queue.runInTransaction { database in - let statusArray = statuses.map { $0.databaseDictionary() } - self.insertRows(statusArray, insertType: .orReplace, in: database) - if let completion = completion { - callVoidCompletionBlock(completion) - } + func insertStatuses(_ statuses: [SyncStatus], completion: DatabaseCompletionBlock? = nil) { + queue.runInTransaction { databaseResult in + + func makeDatabaseCall(_ database: FMDatabase) { + let statusArray = statuses.map { $0.databaseDictionary() } + self.insertRows(statusArray, insertType: .orReplace, in: database) + } + + switch databaseResult { + case .success(let database): + makeDatabaseCall(database) + callCompletion(completion, nil) + case .failure(let databaseError): + callCompletion(completion, databaseError) + } } } } @@ -125,3 +151,12 @@ private extension SyncStatusTable { return SyncStatus(articleID: articleID, key: key, flag: flag, selected: selected) } } + +private func callCompletion(_ completion: DatabaseCompletionBlock?, _ databaseError: DatabaseError?) { + guard let completion = completion else { + return + } + DispatchQueue.main.async { + completion(databaseError) + } +}