Digital PCT265 story ONEAPP-7249 - Polling behavior fixes and logging for clarity.

This commit is contained in:
Hedden, Kyle Matthew 2024-04-30 20:36:49 -04:00
parent 0ab05f4206
commit 3f77a261bc
2 changed files with 52 additions and 5 deletions

View File

@ -0,0 +1,9 @@
//
// MoleculeComparisonProtocol.swift
// MVMCoreUI
//
// Created by Kyle Hedden on 4/29/24.
// Copyright © 2024 Verizon Wireless. All rights reserved.
//
import Foundation

View File

@ -8,6 +8,7 @@
import Foundation
import MVMCore
import Combine
public class PollingBehaviorModel: PageBehaviorModelProtocol {
public class var identifier: String { "pollingBehavior" }
@ -47,15 +48,24 @@ public class PollingBehaviorModel: PageBehaviorModelProtocol {
}
}
public class PollingBehavior: NSObject, PageVisibilityBehavior {
extension PollingBehaviorModel: CustomDebugStringConvertible {
public var debugDescription: String {
return "\(Self.self) @ \(refreshInterval) firing \(self.refreshAction)"
}
}
public class PollingBehavior: NSObject, PageVisibilityBehavior, PageMoleculeTransformationBehavior, CoreLogging {
public static var loggingCategory: String? { return String(describing: Self.self) }
var model: PollingBehaviorModel
var delegateObject: MVMCoreUIDelegateObject?
var lastRefresh = Date.distantPast
var lastRefresh = Date() // Treat the last refresh as now on init. refreshOnShown will bypass otherwise.
var pollTimer: DispatchSourceTimer?
var backgroundEventSubscripiton: AnyCancellable?
var remainingTimeToRefresh: TimeInterval {
lastRefresh.timeIntervalSinceNow - model.refreshInterval
model.refreshInterval + lastRefresh.timeIntervalSinceNow // timeIntervalSinceNow in negative since earlier recording (--)
}
var firstTimeLoad = true
@ -71,6 +81,14 @@ public class PollingBehavior: NSObject, PageVisibilityBehavior {
public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) {
self.model = model as! PollingBehaviorModel
self.delegateObject = delegateObject
Self.debugLog("Initializing for \(model)")
}
public func onPageNew(rootMolecules: [any MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {
if let behaviorVC = delegateObject?.moleculeDelegate as? ViewController, MVMCoreUIUtility.getCurrentVisibleController() == behaviorVC {
// If behavior is initialized after the page is shown, we need to start the timer.
resumePollingTimer(withRemainingTime: refreshOnShown ? 0 : remainingTimeToRefresh, refreshAction: model.refreshAction, interval: model.refreshInterval)
}
}
public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) {
@ -79,23 +97,43 @@ public class PollingBehavior: NSObject, PageVisibilityBehavior {
public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {
pollTimer?.cancel()
backgroundEventSubscripiton = nil
}
func resumePollingTimer(withRemainingTime timeRemaining: TimeInterval, refreshAction: ActionModelProtocol, interval: TimeInterval) {
let delegateObject = delegateObject
pollTimer?.cancel()
let pollingId = UUID().uuidString
debugLog("Scheduling timed event \(pollingId) in \(timeRemaining), interval: \(interval)")
pollTimer = DispatchSource.makeTimerSource()
pollTimer?.schedule(deadline: .now() + timeRemaining, repeating: interval)
pollTimer?.setEventHandler(qos:.utility) {
Task {
pollTimer?.setEventHandler(qos:.utility) { [weak self] in
guard let self = self else { return }
lastRefresh = Date()
Task { [weak self] in
self?.debugLog("Firing timed event \(pollingId), \(refreshAction)")
if let delegateActionHandler = delegateObject?.actionDelegate as? ActionDelegateProtocol {
try? await delegateActionHandler.performAction(with: refreshAction, additionalData: nil, delegateObject: delegateObject)
} else {
try? await MVMCoreActionHandler.shared()?.handleAction(with: refreshAction, additionalData: nil, delegateObject: delegateObject)
}
self?.debugLog("Finished timed event \(pollingId)")
}
}
pollTimer?.resume()
setupBackgroundingPause()
}
private func setupBackgroundingPause() {
backgroundEventSubscripiton = NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification).sink { [weak self] _ in
guard let self = self else { return }
pollTimer?.cancel()
backgroundEventSubscripiton = NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification).sink { [weak self] _ in
guard let self = self else { return }
resumePollingTimer(withRemainingTime: remainingTimeToRefresh, refreshAction: model.refreshAction, interval: model.refreshInterval)
}
}
}
deinit {