blob: 9a8926332d34c685233a64ce107b71b754af0c90 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
//
// AccountDataThrottling.swift
// MullvadVPN
//
// Created by pronebird on 09/08/2022.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import Foundation
import MullvadTypes
/// Struct used for throttling UI calls to update account data via tunnel manager.
struct AccountDataThrottling {
/// Default cooldown interval between requests.
private static let defaultWaitInterval: Duration = .minutes(1)
/// Cooldown interval used when account has already expired.
private static let waitIntervalForExpiredAccount: Duration = .seconds(10)
/// Interval in days when account is considered to be close to expiry.
private static let closeToExpiryDays = 4
enum Condition {
/// Always update account data.
case always
/// Only update account data when account is close to expiry or already expired.
case whenCloseToExpiryAndBeyond
}
let tunnelManager: TunnelManager
private(set) var lastUpdate: Date?
init(tunnelManager: TunnelManager) {
self.tunnelManager = tunnelManager
}
mutating func requestUpdate(condition: Condition) {
guard let accountData = tunnelManager.deviceState.accountData else {
return
}
let now = Date()
switch condition {
case .always:
break
case .whenCloseToExpiryAndBeyond:
guard
let closeToExpiry = Calendar.current.date(
byAdding: .day,
value: Self.closeToExpiryDays * -1,
to: accountData.expiry
)
else { return }
if closeToExpiry > now {
return
}
}
let waitInterval =
accountData.expiry > now
? Self.defaultWaitInterval
: Self.waitIntervalForExpiredAccount
let nextUpdateAfter = lastUpdate?.addingTimeInterval(waitInterval.timeInterval)
let comparisonResult = nextUpdateAfter?.compare(now) ?? .orderedAscending
switch comparisonResult {
case .orderedAscending, .orderedSame:
lastUpdate = now
tunnelManager.updateAccountData()
case .orderedDescending:
break
}
}
mutating func reset() {
lastUpdate = nil
}
}
|