Fix numerous build errors.

This commit is contained in:
Brent Simmons 2024-03-13 21:50:22 -07:00
parent ace9f8ea30
commit c2aa49803f
13 changed files with 60 additions and 173 deletions

View File

@ -645,31 +645,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
fetchUnreadCounts(for: feeds, completion: completion)
}
public func fetchArticles(_ fetchType: FetchType) throws -> Set<Article> {
switch fetchType {
case .starred(let limit):
return try fetchStarredArticles(limit: limit)
case .unread(let limit):
return try fetchUnreadArticles(limit: limit)
case .today(let limit):
return try fetchTodayArticles(limit: limit)
case .folder(let folder, let readFilter):
if readFilter {
return try fetchUnreadArticles(folder: folder)
} else {
return try fetchArticles(folder: folder)
}
case .feed(let feed):
return try fetchArticles(feed: feed)
case .articleIDs(let articleIDs):
return try fetchArticles(articleIDs: articleIDs)
case .search(let searchString):
return try fetchArticlesMatching(searchString)
case .searchWithArticleIDs(let searchString, let articleIDs):
return try fetchArticlesMatchingWithArticleIDs(searchString, articleIDs)
}
}
public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) {
switch fetchType {
case .starred(let limit):
@ -934,11 +909,13 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
public func debugRunSearch() {
#if DEBUG
Task {
let t1 = Date()
let articles = try! fetchArticlesMatching("Brent NetNewsWire")
let articles = try! await fetchArticlesMatching("Brent NetNewsWire")
let t2 = Date()
print(t2.timeIntervalSince(t1))
print(articles.count)
}
#endif
}
@ -1022,52 +999,26 @@ extension Account: FeedMetadataDelegate {
private extension Account {
func fetchStarredArticles(limit: Int?) throws -> Set<Article> {
return try database.fetchStarredArticles(flattenedFeeds().feedIDs(), limit)
}
func fetchStarredArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
database.fetchedStarredArticlesAsync(flattenedFeeds().feedIDs(), limit, completion)
}
func fetchUnreadArticles(limit: Int?) throws -> Set<Article> {
return try fetchUnreadArticles(forContainer: self, limit: limit)
}
func fetchUnreadArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
fetchUnreadArticlesAsync(forContainer: self, limit: limit, completion)
}
func fetchTodayArticles(limit: Int?) throws -> Set<Article> {
return try database.fetchTodayArticles(flattenedFeeds().feedIDs(), limit)
}
func fetchTodayArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
database.fetchTodayArticlesAsync(flattenedFeeds().feedIDs(), limit, completion)
}
func fetchArticles(folder: Folder) throws -> Set<Article> {
return try fetchArticles(forContainer: folder)
}
func fetchArticlesAsync(folder: Folder, _ completion: @escaping ArticleSetResultBlock) {
fetchArticlesAsync(forContainer: folder, completion)
}
func fetchUnreadArticles(folder: Folder) throws -> Set<Article> {
return try fetchUnreadArticles(forContainer: folder, limit: nil)
}
func fetchUnreadArticlesAsync(folder: Folder, _ completion: @escaping ArticleSetResultBlock) {
fetchUnreadArticlesAsync(forContainer: folder, limit: nil, completion)
}
func fetchArticles(feed: Feed) throws -> Set<Article> {
let articles = try database.fetchArticles(feed.feedID)
validateUnreadCount(feed, articles)
return articles
}
func fetchArticlesAsync(feed: Feed, _ completion: @escaping ArticleSetResultBlock) {
database.fetchArticlesAsync(feed.feedID) { [weak self] articleSetResult in
switch articleSetResult {
@ -1080,14 +1031,12 @@ private extension Account {
}
}
func fetchArticlesMatching(_ searchString: String) throws -> Set<Article> {
return try database.fetchArticlesMatching(searchString, flattenedFeeds().feedIDs())
func fetchArticlesMatching(_ searchString: String) async throws -> Set<Article> {
let feedIDs = flattenedFeeds().feedIDs()
return try await database.articlesMatching(searchString: searchString, feedIDs: feedIDs)
}
func fetchArticlesMatchingWithArticleIDs(_ searchString: String, _ articleIDs: Set<String>) throws -> Set<Article> {
return try database.fetchArticlesMatchingWithArticleIDs(searchString, articleIDs)
}
func fetchArticlesMatchingAsync(_ searchString: String, _ completion: @escaping ArticleSetResultBlock) {
database.fetchArticlesMatchingAsync(searchString, flattenedFeeds().feedIDs(), completion)
}
@ -1096,27 +1045,10 @@ private extension Account {
database.fetchArticlesMatchingWithArticleIDsAsync(searchString, articleIDs, completion)
}
func fetchArticles(articleIDs: Set<String>) throws -> Set<Article> {
return try database.fetchArticles(articleIDs: articleIDs)
}
func fetchArticlesAsync(articleIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
return database.fetchArticlesAsync(articleIDs: articleIDs, completion)
}
func fetchUnreadArticles(feed: Feed) throws -> Set<Article> {
let articles = try database.fetchUnreadArticles(Set([feed.feedID]), nil)
validateUnreadCount(feed, articles)
return articles
}
func fetchArticles(forContainer container: Container) throws -> Set<Article> {
let feeds = container.flattenedFeeds()
let articles = try database.fetchArticles(feeds.feedIDs())
validateUnreadCountsAfterFetchingUnreadArticles(feeds, articles)
return articles
}
func fetchArticlesAsync(forContainer container: Container, _ completion: @escaping ArticleSetResultBlock) {
let feeds = container.flattenedFeeds()
database.fetchArticlesAsync(feeds.feedIDs()) { [weak self] (articleSetResult) in
@ -1130,19 +1062,6 @@ private extension Account {
}
}
func fetchUnreadArticles(forContainer container: Container, limit: Int?) throws -> Set<Article> {
let feeds = container.flattenedFeeds()
let articles = try database.fetchUnreadArticles(feeds.feedIDs(), limit)
// We don't validate limit queries because they, by definition, won't correctly match the
// complete unread state for the given container.
if limit == nil {
validateUnreadCountsAfterFetchingUnreadArticles(feeds, articles)
}
return articles
}
func fetchUnreadArticlesAsync(forContainer container: Container, limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
let feeds = container.flattenedFeeds()
database.fetchUnreadArticlesAsync(feeds.feedIDs(), limit) { [weak self] (articleSetResult) in

View File

@ -344,17 +344,7 @@ public final class AccountManager: UnreadCountProvider {
// These fetch articles from active accounts and return a merged Set<Article>.
public func fetchArticles(_ fetchType: FetchType) throws -> Set<Article> {
precondition(Thread.isMainThread)
var articles = Set<Article>()
for account in activeAccounts {
articles.formUnion(try account.fetchArticles(fetchType))
}
return articles
}
public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) {
public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) {
precondition(Thread.isMainThread)
guard activeAccounts.count > 0 else {

View File

@ -12,18 +12,12 @@ import ArticlesDatabase
public protocol ArticleFetcher {
func fetchArticles() throws -> Set<Article>
func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock)
func fetchUnreadArticles() throws -> Set<Article>
func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock)
}
extension Feed: ArticleFetcher {
public func fetchArticles() throws -> Set<Article> {
return try account?.fetchArticles(.feed(self)) ?? Set<Article>()
}
public func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
guard let account = account else {
assertionFailure("Expected feed.account, but got nil.")
@ -33,10 +27,6 @@ extension Feed: ArticleFetcher {
account.fetchArticlesAsync(.feed(self), completion)
}
public func fetchUnreadArticles() throws -> Set<Article> {
return try fetchArticles().unreadArticles()
}
public func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
guard let account = account else {
assertionFailure("Expected feed.account, but got nil.")
@ -56,14 +46,6 @@ extension Feed: ArticleFetcher {
extension Folder: ArticleFetcher {
public func fetchArticles() throws -> Set<Article> {
guard let account = account else {
assertionFailure("Expected folder.account, but got nil.")
return Set<Article>()
}
return try account.fetchArticles(.folder(self, false))
}
public func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
guard let account = account else {
assertionFailure("Expected folder.account, but got nil.")
@ -73,14 +55,6 @@ extension Folder: ArticleFetcher {
account.fetchArticlesAsync(.folder(self, false), completion)
}
public func fetchUnreadArticles() throws -> Set<Article> {
guard let account = account else {
assertionFailure("Expected folder.account, but got nil.")
return Set<Article>()
}
return try account.fetchArticles(.folder(self, true))
}
public func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
guard let account = account else {
assertionFailure("Expected folder.account, but got nil.")

View File

@ -64,8 +64,8 @@ final class CloudKitAccountDelegate: AccountDelegate {
accountZone = CloudKitAccountZone(container: container)
articlesZone = CloudKitArticlesZone(container: container)
let databaseFilePath = (dataFolder as NSString).appendingPathComponent("Sync.sqlite3")
database = SyncDatabase(databaseFilePath: databaseFilePath)
let databasePath = (dataFolder as NSString).appendingPathComponent("Sync.sqlite3")
database = SyncDatabase(databasePath: databasePath)
}
func receiveRemoteNotification(for account: Account, userInfo: [AnyHashable : Any], completion: @escaping () -> Void) {
@ -427,8 +427,10 @@ final class CloudKitAccountDelegate: AccountDelegate {
accountZone.delegate = CloudKitAcountZoneDelegate(account: account, refreshProgress: refreshProgress, articlesZone: articlesZone)
articlesZone.delegate = CloudKitArticlesZoneDelegate(account: account, database: database, articlesZone: articlesZone)
database.resetAllSelectedForProcessing()
Task {
try await database.resetAllSelectedForProcessing()
}
// Check to see if this is a new account and initialize anything we need
if account.externalID == nil {
accountZone.findOrCreateAccount() { result in
@ -443,7 +445,6 @@ final class CloudKitAccountDelegate: AccountDelegate {
accountZone.subscribeToZoneChanges()
articlesZone.subscribeToZoneChanges()
}
}
func accountWillBeDeleted(_ account: Account) {
@ -458,16 +459,24 @@ final class CloudKitAccountDelegate: AccountDelegate {
// MARK: Suspend and Resume (for iOS)
func suspendNetwork() {
refresher.suspend()
}
func suspendDatabase() {
database.suspend()
Task {
await database.suspend()
}
}
func resume() {
refresher.resume()
database.resume()
Task {
await database.resume()
}
}
}

View File

@ -121,7 +121,7 @@ private extension CloudKitSendStatusOperation {
return CloudKitArticleStatusUpdate(articleID: key, statuses: value, article: articlesDict[key])
}
func done(_ stop: Bool) {
@Sendable func done(_ stop: Bool) {
// Don't clear the last one since we might have had additional ticks added
if self.showProgress && self.refreshProgress?.numberRemaining ?? 0 > 1 {
self.refreshProgress?.completeTask()

View File

@ -604,13 +604,19 @@ final class FeedbinAccountDelegate: AccountDelegate {
/// Suspend the SQLLite databases
func suspendDatabase() {
database.suspend()
Task {
await database.suspend()
}
}
/// Make sure no SQLite databases are open and we are ready to issue network requests.
func resume() {
caller.resume()
database.resume()
Task {
await database.resume()
}
}
}
@ -957,13 +963,17 @@ private extension FeedbinAccountDelegate {
apiCall(articleIDGroup) { result in
switch result {
case .success:
self.database.deleteSelectedForProcessing(articleIDGroup.map { String($0) } )
group.leave()
Task {
try? await self.database.deleteSelectedForProcessing(articleIDGroup.map { String($0) } )
group.leave()
}
case .failure(let error):
errorOccurred = true
os_log(.error, log: self.log, "Article status sync call failed: %@.", error.localizedDescription)
self.database.resetSelectedForProcessing(articleIDGroup.map { String($0) } )
group.leave()
Task {
try? await self.database.resetSelectedForProcessing(articleIDGroup.map { String($0) } )
group.leave()
}
}
}
@ -976,7 +986,6 @@ private extension FeedbinAccountDelegate {
completion(.success(()))
}
}
}
func renameFolderRelationship(for account: Account, fromName: String, toName: String) {

View File

@ -661,12 +661,18 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
/// Suspend the SQLLite databases
func suspendDatabase() {
database.suspend()
Task {
await database.suspend()
}
}
/// Make sure no SQLite databases are open and we are ready to issue network requests.
func resume() {
database.resume()
Task {
await database.resume()
}
}
}
@ -885,12 +891,16 @@ private extension ReaderAPIAccountDelegate {
apiCall(articleIDGroup) { result in
switch result {
case .success:
self.database.deleteSelectedForProcessing(articleIDGroup.map { $0 } )
group.leave()
Task {
try? await self.database.deleteSelectedForProcessing(articleIDGroup.map { $0 } )
group.leave()
}
case .failure(let error):
os_log(.error, log: self.log, "Article status sync call failed: %@.", error.localizedDescription)
self.database.resetSelectedForProcessing(articleIDGroup.map { $0 } )
group.leave()
Task {
try? await self.database.resetSelectedForProcessing(articleIDGroup.map { $0 } )
group.leave()
}
}
}

View File

@ -20,18 +20,10 @@ public struct SingleArticleFetcher: ArticleFetcher {
self.articleID = articleID
}
public func fetchArticles() throws -> Set<Article> {
return try account.fetchArticles(.articleIDs(Set([articleID])))
}
public func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
return account.fetchArticlesAsync(.articleIDs(Set([articleID])), completion)
}
public func fetchUnreadArticles() throws -> Set<Article> {
return try account.fetchArticles(.articleIDs(Set([articleID])))
}
public func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
return account.fetchArticlesAsync(.articleIDs(Set([articleID])), completion)
}

View File

@ -61,7 +61,7 @@ class FeedlyTestSupport {
init() {
let dataFolder = try! FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
path = dataFolder.appendingPathComponent("\(UUID().uuidString)-Sync.sqlite3").path
database = SyncDatabase(databaseFilePath: path)
database = SyncDatabase(databasePath: path)
}
deinit {

View File

@ -21,7 +21,7 @@ public extension FMDatabase {
return database
}
func executeUpdateInTransaction(_ sql : String, withArgumentsIn parameters: [Any]?) {
func executeUpdateInTransaction(_ sql : String, withArgumentsIn parameters: [Any]? = nil) {
beginTransaction()
executeUpdate(sql, withArgumentsIn: parameters)

View File

@ -84,18 +84,10 @@ final class SmartFeed: PseudoFeed {
extension SmartFeed: ArticleFetcher {
func fetchArticles() throws -> Set<Article> {
return try delegate.fetchArticles()
}
func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
delegate.fetchArticlesAsync(completion)
}
func fetchUnreadArticles() throws -> Set<Article> {
return try delegate.fetchUnreadArticles()
}
func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
delegate.fetchUnreadArticlesAsync(completion)
}

View File

@ -66,18 +66,10 @@ final class UnreadFeed: PseudoFeed {
extension UnreadFeed: ArticleFetcher {
func fetchArticles() throws -> Set<Article> {
return try fetchUnreadArticles()
}
func fetchArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
fetchUnreadArticlesAsync(completion)
}
func fetchUnreadArticles() throws -> Set<Article> {
return try AccountManager.shared.fetchArticles(fetchType)
}
func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
AccountManager.shared.fetchArticlesAsync(fetchType, completion)
}

View File

@ -60,7 +60,7 @@ struct SyncStatusTable {
func resetAllSelectedForProcessing(database: FMDatabase) {
let updateSQL = "update syncStatus set selected = false"
database.executeUpdateInTransaction(updateSQL, withArgumentsIn: nil)
database.executeUpdateInTransaction(updateSQL)
}
func resetSelectedForProcessing(_ articleIDs: [String], database: FMDatabase) {