simplify and fix background loading (#288)

* simplify and fix background loading

* start receive loop in the main chat
This commit is contained in:
Evgeny Poberezkin
2022-02-10 15:52:11 +00:00
committed by GitHub
parent 5c24089f9f
commit 86c36f53e4
3 changed files with 31 additions and 64 deletions

View File

@@ -14,22 +14,25 @@ private let receiveTaskId = "chat.simplex.app.receive"
// TCP timeout + 2 sec
private let waitForMessages: TimeInterval = 6
class BGManager {
private var bgTimer: Timer?
private let bgRefreshInterval: TimeInterval = 450
class BGManager {
static let shared = BGManager()
var chatReceiver: ChatReceiver?
var bgTimer: Timer?
var completed = false
func register() {
logger.debug("BGManager.register")
BGTaskScheduler.shared.register(forTaskWithIdentifier: receiveTaskId, using: nil) { task in
self.handleRefresh(RefreshTask(task as! BGAppRefreshTask))
self.handleRefresh(task as! BGAppRefreshTask)
}
}
func schedule() {
logger.debug("BGManager.schedule")
let request = BGAppRefreshTaskRequest(identifier: receiveTaskId)
request.earliestBeginDate = Date(timeIntervalSinceNow: 10 * 60)
request.earliestBeginDate = Date(timeIntervalSinceNow: bgRefreshInterval)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
@@ -37,61 +40,41 @@ class BGManager {
}
}
private func handleRefresh(_ task: RefreshTask) {
private func handleRefresh(_ task: BGAppRefreshTask) {
logger.debug("BGManager.handleRefresh")
schedule()
task.expirationHandler = {
logger.debug("BGManager.handleRefresh expirationHandler")
ChatReceiver.shared.stop()
task.setTaskCompleted(success: true)
self.completed = false
let completeTask: (String) -> Void = { reason in
logger.debug("BGManager.handleRefresh completeTask: \(reason)")
if !self.completed {
self.completed = true
self.chatReceiver?.stop()
self.chatReceiver = nil
self.bgTimer?.invalidate()
self.bgTimer = nil
task.setTaskCompleted(success: true)
}
}
task.expirationHandler = { completeTask("expirationHandler") }
DispatchQueue.main.async {
initializeChat()
if ChatModel.shared.currentUser == nil {
task.setTaskCompleted(success: true)
completeTask("no current user")
return
}
logger.debug("BGManager.handleRefresh: starting chat")
ChatReceiver.shared.start(bgTask: task)
let cr = ChatReceiver()
self.chatReceiver = cr
cr.start()
RunLoop.current.add(Timer(timeInterval: 2, repeats: true) { timer in
self.bgTimer = timer
logger.debug("BGManager.handleRefresh: timer")
if ChatReceiver.shared.lastMsgTime.distance(to: Date.now) >= waitForMessages {
logger.debug("BGManager.handleRefresh: timer: stopping")
ChatReceiver.shared.stop()
task.setTaskCompleted(success: true)
timer.invalidate()
self.bgTimer = nil
self.bgTimer = timer
if cr.lastMsgTime.distance(to: Date.now) >= waitForMessages {
completeTask("timer (no messages after \(waitForMessages) seconds)")
}
}, forMode: .default)
}
}
func invalidateStopTimer() {
logger.debug("BGManager.invalidateStopTimer?")
if let timer = bgTimer {
timer.invalidate()
bgTimer = nil
logger.debug("BGManager.invalidateStopTimer: done")
}
}
class RefreshTask {
private let task: BGAppRefreshTask
var completed = false
internal init(_ task: BGAppRefreshTask) {
self.task = task
}
var expirationHandler: (() -> Void)? {
set { task.expirationHandler = newValue }
get { task.expirationHandler }
}
func setTaskCompleted(success: Bool) {
if !completed { task.setTaskCompleted(success: success) }
completed = true
}
}
}

View File

@@ -345,19 +345,15 @@ func initializeChat() {
class ChatReceiver {
private var receiveLoop: DispatchWorkItem?
private var receiveMessages = true
private var wasStarted = false
private var _canStop = false
private var _lastMsgTime = Date.now
static let shared = ChatReceiver()
var lastMsgTime: Date { get { _lastMsgTime } }
func start(bgTask: BGManager.RefreshTask? = nil) {
func start() {
logger.debug("ChatReceiver.start")
wasStarted = true
receiveMessages = true
_canStop = true
_lastMsgTime = .now
if receiveLoop != nil { return }
let loop = DispatchWorkItem(qos: .default, flags: []) {
@@ -369,25 +365,16 @@ class ChatReceiver {
logger.error("ChatReceiver.start chatRecvMsg error: \(error.localizedDescription)")
}
}
if let task = bgTask { task.setTaskCompleted(success: true) }
}
receiveLoop = loop
DispatchQueue.global().async(execute: loop)
}
func stop() {
logger.debug("ChatReceiver.stop?")
if !_canStop { return }
logger.debug("ChatReceiver.stop")
receiveMessages = false
receiveLoop?.cancel()
receiveLoop = nil
logger.debug("ChatReceiver.stop: done")
}
func restart() {
logger.debug("ChatReceiver.restart?")
if wasStarted && receiveLoop == nil { start() }
_canStop = false
}
}

View File

@@ -36,9 +36,6 @@ struct SimpleXApp: App {
.onChange(of: scenePhase) { phase in
if phase == .background {
BGManager.shared.schedule()
} else {
BGManager.shared.invalidateStopTimer()
ChatReceiver.shared.restart()
}
}
}