You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SessionMessagingKit/Sending & Receiving/Pollers/CurrentUserPoller.swift

84 lines
3.1 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
//
// stringlint:disable
import Foundation
import Combine
import GRDB
import Sodium
import SessionSnodeKit
import SessionUtilitiesKit
public final class CurrentUserPoller: Poller {
public static var namespaces: [SnodeAPI.Namespace] = [
.default, .configUserProfile, .configContacts, .configConvoInfoVolatile, .configUserGroups
]
// MARK: - Settings
override var namespaces: [SnodeAPI.Namespace] { CurrentUserPoller.namespaces }
override var pollerQueue: DispatchQueue { Threading.pollerQueue }
/// After polling a given snode 6 times we always switch to a new one.
///
/// The reason for doing this is that sometimes a snode will be giving us successful responses while
/// it isn't actually getting messages from other snodes.
override var pollDrainBehaviour: SwarmDrainBehaviour { .limitedReuse(count: 6) }
private let pollInterval: TimeInterval = 1.5
private let retryInterval: TimeInterval = 0.25
private let maxRetryInterval: TimeInterval = 15
// MARK: - Convenience Functions
public func start(using dependencies: Dependencies = Dependencies()) {
let publicKey: String = getUserHexEncodedPublicKey(using: dependencies)
guard isPolling.wrappedValue[publicKey] != true else { return }
SNLog("Started polling.")
super.startIfNeeded(for: publicKey, using: dependencies)
}
public func stop() {
SNLog("Stopped polling.")
super.stopAllPollers()
}
// MARK: - Abstract Methods
override func pollerName(for publicKey: String) -> String {
return "Main Poller"
}
override func nextPollDelay(for publicKey: String, using dependencies: Dependencies) -> TimeInterval {
let failureCount: TimeInterval = TimeInterval(failureCount.wrappedValue[publicKey] ?? 0)
// If there have been no failures then just use the 'minPollInterval'
guard failureCount > 0 else { return pollInterval }
// Otherwise use a simple back-off with the 'retryInterval'
let nextDelay: TimeInterval = (retryInterval * (failureCount * 1.2))
return min(maxRetryInterval, nextDelay)
}
override func handlePollError(_ error: Error, for publicKey: String, using dependencies: Dependencies) -> PollerErrorResponse {
if UserDefaults.sharedLokiProject?[.isMainAppActive] != true {
// Do nothing when an error gets throws right after returning from the background (happens frequently)
}
else if
let drainBehaviour: Atomic<SwarmDrainBehaviour> = drainBehaviour.wrappedValue[publicKey],
case .limitedReuse(_, .some(let targetSnode), _, _, _) = drainBehaviour.wrappedValue
{
drainBehaviour.mutate { $0 = $0.clearTargetSnode() }
return .continuePollingInfo("Switching from \(targetSnode) to next snode.")
}
else {
return .continuePollingInfo("Had no target snode.")
}
return .continuePolling
}
}