From 583210c7fb05a464ce044ef32db184ab3ee76952 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Feb 2023 22:14:12 +0400 Subject: [PATCH] DB optimizations --- submodules/Postbox/Sources/MediaBox.swift | 8 +-- submodules/Postbox/Sources/Postbox.swift | 13 ++--- .../Postbox/Sources/SqliteValueBox.swift | 2 +- .../Sources/SharedWakeupManager.swift | 50 +++++++++++++++++-- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/submodules/Postbox/Sources/MediaBox.swift b/submodules/Postbox/Sources/MediaBox.swift index 43d72b141c..f3d4ff5c33 100644 --- a/submodules/Postbox/Sources/MediaBox.swift +++ b/submodules/Postbox/Sources/MediaBox.swift @@ -182,9 +182,9 @@ public final class MediaBox { } lazy var ensureDirectoryCreated: Void = { - try! FileManager.default.createDirectory(atPath: self.basePath, withIntermediateDirectories: true, attributes: nil) - try! FileManager.default.createDirectory(atPath: self.basePath + "/cache", withIntermediateDirectories: true, attributes: nil) - try! FileManager.default.createDirectory(atPath: self.basePath + "/short-cache", withIntermediateDirectories: true, attributes: nil) + let _ = try? FileManager.default.createDirectory(atPath: self.basePath, withIntermediateDirectories: true, attributes: nil) + let _ = try? FileManager.default.createDirectory(atPath: self.basePath + "/cache", withIntermediateDirectories: true, attributes: nil) + let _ = try? FileManager.default.createDirectory(atPath: self.basePath + "/short-cache", withIntermediateDirectories: true, attributes: nil) }() public init(basePath: String) { @@ -677,7 +677,7 @@ public final class MediaBox { if let file = ManagedFile(queue: nil, path: paths.complete, mode: .read) { let clippedLowerBound = min(completeSize, max(0, range.lowerBound)) let clippedUpperBound = min(completeSize, max(0, range.upperBound)) - if clippedLowerBound < clippedUpperBound { + if clippedLowerBound < clippedUpperBound && (clippedUpperBound - clippedLowerBound) <= 64 * 1024 * 1024 { file.seek(position: clippedLowerBound) let data = file.readData(count: Int(clippedUpperBound - clippedLowerBound)) subscriber.putNext((data, true)) diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 17f075d869..eb759bbf19 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -2600,7 +2600,7 @@ final class PostboxImpl { } let canBeginTransactionsValue = Atomic(value: true) - public func setCanBeginTransactions(_ value: Bool) { + public func setCanBeginTransactions(_ value: Bool, afterTransactionIfRunning: @escaping () -> Void) { self.queue.async { let previous = self.canBeginTransactionsValue.swap(value) if previous != value && value { @@ -2609,6 +2609,7 @@ final class PostboxImpl { f() } } + afterTransactionIfRunning() } } @@ -3911,15 +3912,9 @@ public class Postbox { } } - public func setCanBeginTransactions(_ value: Bool) { - #if DEBUG - if !value { - assert(!self.isInTransaction.with({ $0 })) - } - #endif - + public func setCanBeginTransactions(_ value: Bool, afterTransactionIfRunning: @escaping () -> Void = {}) { self.impl.with { impl in - impl.setCanBeginTransactions(value) + impl.setCanBeginTransactions(value, afterTransactionIfRunning: afterTransactionIfRunning) } } diff --git a/submodules/Postbox/Sources/SqliteValueBox.swift b/submodules/Postbox/Sources/SqliteValueBox.swift index 3a573851ff..56d63d63eb 100644 --- a/submodules/Postbox/Sources/SqliteValueBox.swift +++ b/submodules/Postbox/Sources/SqliteValueBox.swift @@ -565,7 +565,7 @@ public final class SqliteValueBox: ValueBox { let allIsOk = Atomic(value: false) let removeDatabaseOnError = self.removeDatabaseOnError let databasePath = self.databasePath - DispatchQueue.global().asyncAfter(deadline: .now() + 5.0, execute: { + DispatchQueue.global().asyncAfter(deadline: .now() + 15.0, execute: { if allIsOk.with({ $0 }) == false { postboxLog("Timeout reached, discarding database") if removeDatabaseOnError { diff --git a/submodules/TelegramUI/Sources/SharedWakeupManager.swift b/submodules/TelegramUI/Sources/SharedWakeupManager.swift index e0cfcb2de8..b7b8517ea6 100644 --- a/submodules/TelegramUI/Sources/SharedWakeupManager.swift +++ b/submodules/TelegramUI/Sources/SharedWakeupManager.swift @@ -305,6 +305,8 @@ public final class SharedWakeupManager { } } + var endTaskAfterTransactionsComplete: UIBackgroundTaskIdentifier? + if self.inForeground || self.hasActiveAudioSession || hasActiveCalls { if let (completion, timer) = self.currentExternalCompletion { self.currentExternalCompletion = nil @@ -389,12 +391,15 @@ public final class SharedWakeupManager { } } else if let (taskId, _, timer) = self.currentTask { self.currentTask = nil + timer.invalidate() - self.endBackgroundTask(taskId) + + endTaskAfterTransactionsComplete = taskId + self.isInBackgroundExtension = false } } - self.updateAccounts(hasTasks: hasTasksForBackgroundExtension) + self.updateAccounts(hasTasks: hasTasksForBackgroundExtension, endTaskAfterTransactionsComplete: endTaskAfterTransactionsComplete) if hasPendingMessages { if self.keepIdleDisposable == nil { @@ -408,7 +413,7 @@ public final class SharedWakeupManager { } } - private func updateAccounts(hasTasks: Bool) { + private func updateAccounts(hasTasks: Bool, endTaskAfterTransactionsComplete: UIBackgroundTaskIdentifier?) { if self.inForeground || self.hasActiveAudioSession || self.isInBackgroundExtension || (hasTasks && self.currentExternalCompletion != nil) || self.activeExplicitExtensionTimer != nil { Logger.shared.log("Wakeup", "enableBeginTransactions: true (active)") @@ -424,18 +429,55 @@ public final class SharedWakeupManager { account.shouldKeepOnlinePresence.set(.single(primary && self.inForeground)) account.shouldKeepBackgroundDownloadConnections.set(.single(tasks.backgroundDownloads)) } + + if let endTaskAfterTransactionsComplete { + self.endBackgroundTask(endTaskAfterTransactionsComplete) + } } else { var enableBeginTransactions = false if self.allowBackgroundTimeExtensionDeadlineTimer != nil { enableBeginTransactions = true } Logger.shared.log("Wakeup", "enableBeginTransactions: \(enableBeginTransactions)") + + final class CompletionObservationState { + var isCompleted: Bool = false + var remainingAccounts: [AccountRecordId] + + init(remainingAccounts: [AccountRecordId]) { + self.remainingAccounts = remainingAccounts + } + } + let completionState = Atomic(value: CompletionObservationState(remainingAccounts: self.accountsAndTasks.map(\.0.id))) + let checkCompletionState: (AccountRecordId?) -> Void = { id in + Queue.mainQueue().async { + var shouldComplete = false + completionState.with { state in + if let id { + state.remainingAccounts.removeAll(where: { $0 == id }) + } + if state.remainingAccounts.isEmpty && !state.isCompleted { + state.isCompleted = true + shouldComplete = true + } + } + if shouldComplete, let endTaskAfterTransactionsComplete { + self.endBackgroundTask(endTaskAfterTransactionsComplete) + } + } + } + for (account, _, _) in self.accountsAndTasks { - account.postbox.setCanBeginTransactions(enableBeginTransactions) + let accountId = account.id + account.postbox.setCanBeginTransactions(enableBeginTransactions, afterTransactionIfRunning: { + checkCompletionState(accountId) + }) account.shouldBeServiceTaskMaster.set(.single(.never)) account.shouldKeepOnlinePresence.set(.single(false)) account.shouldKeepBackgroundDownloadConnections.set(.single(false)) } + + checkCompletionState(nil) } } }